1 /*
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package java.awt;
26
27 import java.awt.event.FocusEvent;
28 import java.awt.event.InputEvent;
29 import java.awt.event.KeyEvent;
30 import java.awt.event.WindowEvent;
31
32 import java.awt.peer.KeyboardFocusManagerPeer;
33 import java.awt.peer.LightweightPeer;
34
35 import java.beans.PropertyChangeListener;
36 import java.beans.PropertyChangeSupport;
37 import java.beans.PropertyVetoException;
38 import java.beans.VetoableChangeListener;
39 import java.beans.VetoableChangeSupport;
40
41 import java.lang.ref.WeakReference;
42
43 import java.lang.reflect.Field;
44
45 import java.security.AccessController;
46 import java.security.PrivilegedAction;
47
48 import java.util.Collections;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.LinkedList;
52 import java.util.Set;
53 import java.util.StringTokenizer;
54 import java.util.WeakHashMap;
55
56 import sun.util.logging.PlatformLogger;
57
58 import sun.awt.AppContext;
59 import sun.awt.HeadlessToolkit;
60 import sun.awt.SunToolkit;
61 import sun.awt.CausedFocusEvent;
62 import sun.awt.KeyboardFocusManagerPeerProvider;
63 import sun.awt.AWTAccessor;
64
65 /**
66 * The KeyboardFocusManager is responsible for managing the active and focused
67 * Windows, and the current focus owner. The focus owner is defined as the
68 * Component in an application that will typically receive all KeyEvents
69 * generated by the user. The focused Window is the Window that is, or
70 * contains, the focus owner. Only a Frame or a Dialog can be the active
71 * Window. The native windowing system may denote the active Window or its
72 * children with special decorations, such as a highlighted title bar. The
73 * active Window is always either the focused Window, or the first Frame or
74 * Dialog that is an owner of the focused Window.
75 * <p>
76 * The KeyboardFocusManager is both a centralized location for client code to
77 * query for the focus owner and initiate focus changes, and an event
78 * dispatcher for all FocusEvents, WindowEvents related to focus, and
79 * KeyEvents.
80 * <p>
81 * Some browsers partition applets in different code bases into separate
82 * contexts, and establish walls between these contexts. In such a scenario,
83 * there will be one KeyboardFocusManager per context. Other browsers place all
84 * applets into the same context, implying that there will be only a single,
85 * global KeyboardFocusManager for all applets. This behavior is
86 * implementation-dependent. Consult your browser's documentation for more
87 * information. No matter how many contexts there may be, however, there can
88 * never be more than one focus owner, focused Window, or active Window, per
89 * ClassLoader.
90 * <p>
91 * Please see
92 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
93 * How to Use the Focus Subsystem</a>,
94 * a section in <em>The Java Tutorial</em>, and the
95 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
96 * for more information.
97 *
98 * @author David Mendenhall
99 *
100 * @see Window
101 * @see Frame
102 * @see Dialog
103 * @see java.awt.event.FocusEvent
104 * @see java.awt.event.WindowEvent
105 * @see java.awt.event.KeyEvent
106 * @since 1.4
107 */
108 public abstract class KeyboardFocusManager
109 implements KeyEventDispatcher, KeyEventPostProcessor
110 {
111
112 // Shared focus engine logger
113 private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
114
115 static {
116 /* ensure that the necessary native libraries are loaded */
117 Toolkit.loadLibraries();
118 if (!GraphicsEnvironment.isHeadless()) {
119 initIDs();
120 }
121 AWTAccessor.setKeyboardFocusManagerAccessor(
122 new AWTAccessor.KeyboardFocusManagerAccessor() {
123 public int shouldNativelyFocusHeavyweight(Component heavyweight,
124 Component descendant,
125 boolean temporary,
126 boolean focusedWindowChangeAllowed,
127 long time,
128 CausedFocusEvent.Cause cause)
129 {
130 return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
131 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
132 }
133 public boolean processSynchronousLightweightTransfer(Component heavyweight,
134 Component descendant,
135 boolean temporary,
136 boolean focusedWindowChangeAllowed,
137 long time)
138 {
139 return KeyboardFocusManager.processSynchronousLightweightTransfer(
140 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
141 }
142 public void removeLastFocusRequest(Component heavyweight) {
143 KeyboardFocusManager.removeLastFocusRequest(heavyweight);
144 }
145 public void setMostRecentFocusOwner(Window window, Component component) {
146 KeyboardFocusManager.setMostRecentFocusOwner(window, component);
147 }
148 }
149 );
150 }
151
152 transient KeyboardFocusManagerPeer peer;
153
154 /**
155 * Initialize JNI field and method IDs
156 */
157 private static native void initIDs();
158
159 private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager");
160
161 /**
162 * The identifier for the Forward focus traversal keys.
163 *
164 * @see #setDefaultFocusTraversalKeys
165 * @see #getDefaultFocusTraversalKeys
166 * @see Component#setFocusTraversalKeys
167 * @see Component#getFocusTraversalKeys
168 */
169 public static final int FORWARD_TRAVERSAL_KEYS = 0;
170
171 /**
172 * The identifier for the Backward focus traversal keys.
173 *
174 * @see #setDefaultFocusTraversalKeys
175 * @see #getDefaultFocusTraversalKeys
176 * @see Component#setFocusTraversalKeys
177 * @see Component#getFocusTraversalKeys
178 */
179 public static final int BACKWARD_TRAVERSAL_KEYS = 1;
180
181 /**
182 * The identifier for the Up Cycle focus traversal keys.
183 *
184 * @see #setDefaultFocusTraversalKeys
185 * @see #getDefaultFocusTraversalKeys
186 * @see Component#setFocusTraversalKeys
187 * @see Component#getFocusTraversalKeys
188 */
189 public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
190
191 /**
192 * The identifier for the Down Cycle focus traversal keys.
193 *
194 * @see #setDefaultFocusTraversalKeys
195 * @see #getDefaultFocusTraversalKeys
196 * @see Component#setFocusTraversalKeys
197 * @see Component#getFocusTraversalKeys
198 */
199 public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
200
201 static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
202
203 /**
204 * Returns the current KeyboardFocusManager instance for the calling
205 * thread's context.
206 *
207 * @return this thread's context's KeyboardFocusManager
208 * @see #setCurrentKeyboardFocusManager
209 */
210 public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
211 return getCurrentKeyboardFocusManager(AppContext.getAppContext());
212 }
213
214 synchronized static KeyboardFocusManager
215 getCurrentKeyboardFocusManager(AppContext appcontext)
216 {
217 KeyboardFocusManager manager = (KeyboardFocusManager)
218 appcontext.get(KeyboardFocusManager.class);
219 if (manager == null) {
220 manager = new DefaultKeyboardFocusManager();
221 appcontext.put(KeyboardFocusManager.class, manager);
222 }
223 return manager;
224 }
225
226 /**
227 * Sets the current KeyboardFocusManager instance for the calling thread's
228 * context. If null is specified, then the current KeyboardFocusManager
229 * is replaced with a new instance of DefaultKeyboardFocusManager.
230 * <p>
231 * If a SecurityManager is installed, the calling thread must be granted
232 * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
233 * the current KeyboardFocusManager. If this permission is not granted,
234 * this method will throw a SecurityException, and the current
235 * KeyboardFocusManager will be unchanged.
236 *
237 * @param newManager the new KeyboardFocusManager for this thread's context
238 * @see #getCurrentKeyboardFocusManager
239 * @see DefaultKeyboardFocusManager
240 * @throws SecurityException if the calling thread does not have permission
241 * to replace the current KeyboardFocusManager
242 */
243 public static void setCurrentKeyboardFocusManager(
244 KeyboardFocusManager newManager) throws SecurityException
245 {
246 SecurityManager security = System.getSecurityManager();
247 if (security != null) {
248 if (replaceKeyboardFocusManagerPermission == null) {
249 replaceKeyboardFocusManagerPermission =
250 new AWTPermission("replaceKeyboardFocusManager");
251 }
252 security.
253 checkPermission(replaceKeyboardFocusManagerPermission);
254 }
255
256 KeyboardFocusManager oldManager = null;
257
258 synchronized (KeyboardFocusManager.class) {
259 AppContext appcontext = AppContext.getAppContext();
260
261 if (newManager != null) {
262 oldManager = getCurrentKeyboardFocusManager(appcontext);
263
264 appcontext.put(KeyboardFocusManager.class, newManager);
265 } else {
266 oldManager = getCurrentKeyboardFocusManager(appcontext);
267 appcontext.remove(KeyboardFocusManager.class);
268 }
269 }
270
271 if (oldManager != null) {
272 oldManager.firePropertyChange("managingFocus",
273 Boolean.TRUE,
274 Boolean.FALSE);
275 }
276 if (newManager != null) {
277 newManager.firePropertyChange("managingFocus",
278 Boolean.FALSE,
279 Boolean.TRUE);
280 }
281 }
282
283 /**
284 * The Component in an application that will typically receive all
285 * KeyEvents generated by the user.
286 */
287 private static Component focusOwner;
288
289 /**
290 * The Component in an application that will regain focus when an
291 * outstanding temporary focus transfer has completed, or the focus owner,
292 * if no outstanding temporary transfer exists.
293 */
294 private static Component permanentFocusOwner;
295
296 /**
297 * The Window which is, or contains, the focus owner.
298 */
299 private static Window focusedWindow;
300
301 /**
302 * Only a Frame or a Dialog can be the active Window. The native windowing
303 * system may denote the active Window with a special decoration, such as a
304 * highlighted title bar. The active Window is always either the focused
305 * Window, or the first Frame or Dialog which is an owner of the focused
306 * Window.
307 */
308 private static Window activeWindow;
309
310 /**
311 * The default FocusTraversalPolicy for all Windows that have no policy of
312 * their own set. If those Windows have focus-cycle-root children that have
313 * no keyboard-traversal policy of their own, then those children will also
314 * inherit this policy (as will, recursively, their focus-cycle-root
315 * children).
316 */
317 private FocusTraversalPolicy defaultPolicy =
318 new DefaultFocusTraversalPolicy();
319
320 /**
321 * The bound property names of each focus traversal key.
322 */
323 private static final String[] defaultFocusTraversalKeyPropertyNames = {
324 "forwardDefaultFocusTraversalKeys",
325 "backwardDefaultFocusTraversalKeys",
326 "upCycleDefaultFocusTraversalKeys",
327 "downCycleDefaultFocusTraversalKeys"
328 };
329
330 /**
331 * The default strokes for initializing the default focus traversal keys.
332 */
333 private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
334 {
335 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
336 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
337 },
338 {
339 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
340 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
341 InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
342 false),
343 },
344 {},
345 {},
346 };
347 /**
348 * The default focus traversal keys. Each array of traversal keys will be
349 * in effect on all Windows that have no such array of their own explicitly
350 * set. Each array will also be inherited, recursively, by any child
351 * Component of those Windows that has no such array of its own explicitly
352 * set.
353 */
354 private Set[] defaultFocusTraversalKeys = new Set[4];
355
356 /**
357 * The current focus cycle root. If the focus owner is itself a focus cycle
358 * root, then it may be ambiguous as to which Components represent the next
359 * and previous Components to focus during normal focus traversal. In that
360 * case, the current focus cycle root is used to differentiate among the
361 * possibilities.
362 */
363 private static Container currentFocusCycleRoot;
364
365 /**
366 * A description of any VetoableChangeListeners which have been registered.
367 */
368 private VetoableChangeSupport vetoableSupport;
369
370 /**
371 * A description of any PropertyChangeListeners which have been registered.
372 */
373 private PropertyChangeSupport changeSupport;
374
375 /**
376 * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
377 * include this KeyboardFocusManager unless it was explicitly re-registered
378 * via a call to <code>addKeyEventDispatcher</code>. If no other
379 * KeyEventDispatchers are registered, this field may be null or refer to
380 * a List of length 0.
381 */
382 private java.util.LinkedList keyEventDispatchers;
383
384 /**
385 * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
386 * not include this KeyboardFocusManager unless it was explicitly
387 * re-registered via a call to <code>addKeyEventPostProcessor</code>.
388 * If no other KeyEventPostProcessors are registered, this field may be
389 * null or refer to a List of length 0.
390 */
391 private java.util.LinkedList keyEventPostProcessors;
392
393 /**
394 * Maps Windows to those Windows' most recent focus owners.
395 */
396 private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
397
398 /**
399 * Error String for initializing SecurityExceptions.
400 */
401 private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
402
403 /**
404 * We cache the permission used to verify that the calling thread is
405 * permitted to access the global focus state.
406 */
407 private static AWTPermission replaceKeyboardFocusManagerPermission;
408
409 /*
410 * SequencedEvent which is currently dispatched in AppContext.
411 */
412 transient SequencedEvent currentSequencedEvent = null;
413
414 final void setCurrentSequencedEvent(SequencedEvent current) {
415 synchronized (SequencedEvent.class) {
416 assert(current == null || currentSequencedEvent == null);
417 currentSequencedEvent = current;
418 }
419 }
420
421 final SequencedEvent getCurrentSequencedEvent() {
422 synchronized (SequencedEvent.class) {
423 return currentSequencedEvent;
424 }
425 }
426
427 static Set initFocusTraversalKeysSet(String value, Set targetSet) {
428 StringTokenizer tokens = new StringTokenizer(value, ",");
429 while (tokens.hasMoreTokens()) {
430 targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
431 }
432 return (targetSet.isEmpty())
433 ? Collections.EMPTY_SET
434 : Collections.unmodifiableSet(targetSet);
435 }
436
437 /**
438 * Initializes a KeyboardFocusManager.
439 */
440 public KeyboardFocusManager() {
441 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
442 Set work_set = new HashSet();
443 for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
444 work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
445 }
446 defaultFocusTraversalKeys[i] = (work_set.isEmpty())
447 ? Collections.EMPTY_SET
448 : Collections.unmodifiableSet(work_set);
449 }
450 initPeer();
451 }
452
453 private void initPeer() {
454 Toolkit tk = Toolkit.getDefaultToolkit();
455 KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk;
456 peer = peerProvider.createKeyboardFocusManagerPeer(this);
457 }
458
459 /**
460 * Returns the focus owner, if the focus owner is in the same context as
461 * the calling thread. The focus owner is defined as the Component in an
462 * application that will typically receive all KeyEvents generated by the
463 * user. KeyEvents which map to the focus owner's focus traversal keys will
464 * not be delivered if focus traversal keys are enabled for the focus
465 * owner. In addition, KeyEventDispatchers may retarget or consume
466 * KeyEvents before they reach the focus owner.
467 *
468 * @return the focus owner, or null if the focus owner is not a member of
469 * the calling thread's context
470 * @see #getGlobalFocusOwner
471 * @see #setGlobalFocusOwner
472 */
473 public Component getFocusOwner() {
474 synchronized (KeyboardFocusManager.class) {
475 if (focusOwner == null) {
476 return null;
477 }
478
479 return (focusOwner.appContext == AppContext.getAppContext())
480 ? focusOwner
481 : null;
482 }
483 }
484
485 /**
486 * Returns the focus owner, even if the calling thread is in a different
487 * context than the focus owner. The focus owner is defined as the
488 * Component in an application that will typically receive all KeyEvents
489 * generated by the user. KeyEvents which map to the focus owner's focus
490 * traversal keys will not be delivered if focus traversal keys are enabled
491 * for the focus owner. In addition, KeyEventDispatchers may retarget or
492 * consume KeyEvents before they reach the focus owner.
493 * <p>
494 * This method will throw a SecurityException if this KeyboardFocusManager
495 * is not the current KeyboardFocusManager for the calling thread's
496 * context.
497 *
498 * @return the focus owner
499 * @see #getFocusOwner
500 * @see #setGlobalFocusOwner
501 * @throws SecurityException if this KeyboardFocusManager is not the
502 * current KeyboardFocusManager for the calling thread's context
503 */
504 protected Component getGlobalFocusOwner() throws SecurityException {
505 synchronized (KeyboardFocusManager.class) {
506 if (this == getCurrentKeyboardFocusManager()) {
507 return focusOwner;
508 } else {
509 if (focusLog.isLoggable(PlatformLogger.FINER)) {
510 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
511 }
512 throw new SecurityException(notPrivileged);
513 }
514 }
515 }
516
517 /**
518 * Sets the focus owner. The operation will be cancelled if the Component
519 * is not focusable. The focus owner is defined as the Component in an
520 * application that will typically receive all KeyEvents generated by the
521 * user. KeyEvents which map to the focus owner's focus traversal keys will
522 * not be delivered if focus traversal keys are enabled for the focus
523 * owner. In addition, KeyEventDispatchers may retarget or consume
524 * KeyEvents before they reach the focus owner.
525 * <p>
526 * This method does not actually set the focus to the specified Component.
527 * It merely stores the value to be subsequently returned by
528 * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
529 * or <code>Component.requestFocusInWindow()</code> to change the focus
530 * owner, subject to platform limitations.
531 *
532 * @param focusOwner the focus owner
533 * @see #getFocusOwner
534 * @see #getGlobalFocusOwner
535 * @see Component#requestFocus()
536 * @see Component#requestFocusInWindow()
537 * @see Component#isFocusable
538 * @beaninfo
539 * bound: true
540 */
541 protected void setGlobalFocusOwner(Component focusOwner) {
542 Component oldFocusOwner = null;
543 boolean shouldFire = false;
544
545 if (focusOwner == null || focusOwner.isFocusable()) {
546 synchronized (KeyboardFocusManager.class) {
547 oldFocusOwner = getFocusOwner();
548
549 try {
550 fireVetoableChange("focusOwner", oldFocusOwner,
551 focusOwner);
552 } catch (PropertyVetoException e) {
553 // rejected
554 return;
555 }
556
557 KeyboardFocusManager.focusOwner = focusOwner;
558
559 if (focusOwner != null &&
560 (getCurrentFocusCycleRoot() == null ||
561 !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
562 {
563 Container rootAncestor =
564 focusOwner.getFocusCycleRootAncestor();
565 if (rootAncestor == null && (focusOwner instanceof Window))
566 {
567 rootAncestor = (Container)focusOwner;
568 }
569 if (rootAncestor != null) {
570 setGlobalCurrentFocusCycleRoot(rootAncestor);
571 }
572 }
573
574 shouldFire = true;
575 }
576 }
577
578 if (shouldFire) {
579 firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
580 }
581 }
582
583 /**
584 * Clears the global focus owner at both the Java and native levels. If
585 * there exists a focus owner, that Component will receive a permanent
586 * FOCUS_LOST event. After this operation completes, the native windowing
587 * system will discard all user-generated KeyEvents until the user selects
588 * a new Component to receive focus, or a Component is given focus
589 * explicitly via a call to <code>requestFocus()</code>. This operation
590 * does not change the focused or active Windows.
591 *
592 * @see Component#requestFocus()
593 * @see java.awt.event.FocusEvent#FOCUS_LOST
594 */
595 public void clearGlobalFocusOwner() {
596 if (!GraphicsEnvironment.isHeadless()) {
597 // Toolkit must be fully initialized, otherwise
598 // _clearGlobalFocusOwner will crash or throw an exception
599 Toolkit.getDefaultToolkit();
600
601 _clearGlobalFocusOwner();
602 }
603 }
604 private void _clearGlobalFocusOwner() {
605 Window activeWindow = markClearGlobalFocusOwner();
606 peer.clearGlobalFocusOwner(activeWindow);
607 }
608
609 Component getNativeFocusOwner() {
610 return peer.getCurrentFocusOwner();
611 }
612
613 void setNativeFocusOwner(Component comp) {
614 if (focusLog.isLoggable(PlatformLogger.FINEST)) {
615 focusLog.finest("Calling peer {0} setCurrentFocusOwner for {1}",
616 String.valueOf(peer), String.valueOf(comp));
617 }
618 peer.setCurrentFocusOwner(comp);
619 }
620
621 Window getNativeFocusedWindow() {
622 return peer.getCurrentFocusedWindow();
623 }
624
625 /**
626 * Returns the permanent focus owner, if the permanent focus owner is in
627 * the same context as the calling thread. The permanent focus owner is
628 * defined as the last Component in an application to receive a permanent
629 * FOCUS_GAINED event. The focus owner and permanent focus owner are
630 * equivalent unless a temporary focus change is currently in effect. In
631 * such a situation, the permanent focus owner will again be the focus
632 * owner when the temporary focus change ends.
633 *
634 * @return the permanent focus owner, or null if the permanent focus owner
635 * is not a member of the calling thread's context
636 * @see #getGlobalPermanentFocusOwner
637 * @see #setGlobalPermanentFocusOwner
638 */
639 public Component getPermanentFocusOwner() {
640 synchronized (KeyboardFocusManager.class) {
641 if (permanentFocusOwner == null) {
642 return null;
643 }
644
645 return (permanentFocusOwner.appContext ==
646 AppContext.getAppContext())
647 ? permanentFocusOwner
648 : null;
649 }
650 }
651
652 /**
653 * Returns the permanent focus owner, even if the calling thread is in a
654 * different context than the permanent focus owner. The permanent focus
655 * owner is defined as the last Component in an application to receive a
656 * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
657 * are equivalent unless a temporary focus change is currently in effect.
658 * In such a situation, the permanent focus owner will again be the focus
659 * owner when the temporary focus change ends.
660 * <p>
661 * This method will throw a SecurityException if this KeyboardFocusManager
662 * is not the current KeyboardFocusManager for the calling thread's
663 * context.
664 *
665 * @return the permanent focus owner
666 * @see #getPermanentFocusOwner
667 * @see #setGlobalPermanentFocusOwner
668 * @throws SecurityException if this KeyboardFocusManager is not the
669 * current KeyboardFocusManager for the calling thread's context
670 */
671 protected Component getGlobalPermanentFocusOwner()
672 throws SecurityException
673 {
674 synchronized (KeyboardFocusManager.class) {
675 if (this == getCurrentKeyboardFocusManager()) {
676 return permanentFocusOwner;
677 } else {
678 if (focusLog.isLoggable(PlatformLogger.FINER)) {
679 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
680 }
681 throw new SecurityException(notPrivileged);
682 }
683 }
684 }
685
686 /**
687 * Sets the permanent focus owner. The operation will be cancelled if the
688 * Component is not focusable. The permanent focus owner is defined as the
689 * last Component in an application to receive a permanent FOCUS_GAINED
690 * event. The focus owner and permanent focus owner are equivalent unless
691 * a temporary focus change is currently in effect. In such a situation,
692 * the permanent focus owner will again be the focus owner when the
693 * temporary focus change ends.
694 * <p>
695 * This method does not actually set the focus to the specified Component.
696 * It merely stores the value to be subsequently returned by
697 * <code>getPermanentFocusOwner()</code>. Use
698 * <code>Component.requestFocus()</code> or
699 * <code>Component.requestFocusInWindow()</code> to change the focus owner,
700 * subject to platform limitations.
701 *
702 * @param permanentFocusOwner the permanent focus owner
703 * @see #getPermanentFocusOwner
704 * @see #getGlobalPermanentFocusOwner
705 * @see Component#requestFocus()
706 * @see Component#requestFocusInWindow()
707 * @see Component#isFocusable
708 * @beaninfo
709 * bound: true
710 */
711 protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
712 {
713 Component oldPermanentFocusOwner = null;
714 boolean shouldFire = false;
715
716 if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
717 synchronized (KeyboardFocusManager.class) {
718 oldPermanentFocusOwner = getPermanentFocusOwner();
719
720 try {
721 fireVetoableChange("permanentFocusOwner",
722 oldPermanentFocusOwner,
723 permanentFocusOwner);
724 } catch (PropertyVetoException e) {
725 // rejected
726 return;
727 }
728
729 KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
730
731 KeyboardFocusManager.
732 setMostRecentFocusOwner(permanentFocusOwner);
733
734 shouldFire = true;
735 }
736 }
737
738 if (shouldFire) {
739 firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
740 permanentFocusOwner);
741 }
742 }
743
744 /**
745 * Returns the focused Window, if the focused Window is in the same context
746 * as the calling thread. The focused Window is the Window that is or
747 * contains the focus owner.
748 *
749 * @return the focused Window, or null if the focused Window is not a
750 * member of the calling thread's context
751 * @see #getGlobalFocusedWindow
752 * @see #setGlobalFocusedWindow
753 */
754 public Window getFocusedWindow() {
755 synchronized (KeyboardFocusManager.class) {
756 if (focusedWindow == null) {
757 return null;
758 }
759
760 return (focusedWindow.appContext == AppContext.getAppContext())
761 ? focusedWindow
762 : null;
763 }
764 }
765
766 /**
767 * Returns the focused Window, even if the calling thread is in a different
768 * context than the focused Window. The focused Window is the Window that
769 * is or contains the focus owner.
770 * <p>
771 * This method will throw a SecurityException if this KeyboardFocusManager
772 * is not the current KeyboardFocusManager for the calling thread's
773 * context.
774 *
775 * @return the focused Window
776 * @see #getFocusedWindow
777 * @see #setGlobalFocusedWindow
778 * @throws SecurityException if this KeyboardFocusManager is not the
779 * current KeyboardFocusManager for the calling thread's context
780 */
781 protected Window getGlobalFocusedWindow() throws SecurityException {
782 synchronized (KeyboardFocusManager.class) {
783 if (this == getCurrentKeyboardFocusManager()) {
784 return focusedWindow;
785 } else {
786 if (focusLog.isLoggable(PlatformLogger.FINER)) {
787 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
788 }
789 throw new SecurityException(notPrivileged);
790 }
791 }
792 }
793
794 /**
795 * Sets the focused Window. The focused Window is the Window that is or
796 * contains the focus owner. The operation will be cancelled if the
797 * specified Window to focus is not a focusable Window.
798 * <p>
799 * This method does not actually change the focused Window as far as the
800 * native windowing system is concerned. It merely stores the value to be
801 * subsequently returned by <code>getFocusedWindow()</code>. Use
802 * <code>Component.requestFocus()</code> or
803 * <code>Component.requestFocusInWindow()</code> to change the focused
804 * Window, subject to platform limitations.
805 *
806 * @param focusedWindow the focused Window
807 * @see #getFocusedWindow
808 * @see #getGlobalFocusedWindow
809 * @see Component#requestFocus()
810 * @see Component#requestFocusInWindow()
811 * @see Window#isFocusableWindow
812 * @beaninfo
813 * bound: true
814 */
815 protected void setGlobalFocusedWindow(Window focusedWindow) {
816 Window oldFocusedWindow = null;
817 boolean shouldFire = false;
818
819 if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
820 synchronized (KeyboardFocusManager.class) {
821 oldFocusedWindow = getFocusedWindow();
822
823 try {
824 fireVetoableChange("focusedWindow", oldFocusedWindow,
825 focusedWindow);
826 } catch (PropertyVetoException e) {
827 // rejected
828 return;
829 }
830
831 KeyboardFocusManager.focusedWindow = focusedWindow;
832 shouldFire = true;
833 }
834 }
835
836 if (shouldFire) {
837 firePropertyChange("focusedWindow", oldFocusedWindow,
838 focusedWindow);
839 }
840 }
841
842 /**
843 * Returns the active Window, if the active Window is in the same context
844 * as the calling thread. Only a Frame or a Dialog can be the active
845 * Window. The native windowing system may denote the active Window or its
846 * children with special decorations, such as a highlighted title bar.
847 * The active Window is always either the focused Window, or the first
848 * Frame or Dialog that is an owner of the focused Window.
849 *
850 * @return the active Window, or null if the active Window is not a member
851 * of the calling thread's context
852 * @see #getGlobalActiveWindow
853 * @see #setGlobalActiveWindow
854 */
855 public Window getActiveWindow() {
856 synchronized (KeyboardFocusManager.class) {
857 if (activeWindow == null) {
858 return null;
859 }
860
861 return (activeWindow.appContext == AppContext.getAppContext())
862 ? activeWindow
863 : null;
864 }
865 }
866
867 /**
868 * Returns the active Window, even if the calling thread is in a different
869 * context than the active Window. Only a Frame or a Dialog can be the
870 * active Window. The native windowing system may denote the active Window
871 * or its children with special decorations, such as a highlighted title
872 * bar. The active Window is always either the focused Window, or the first
873 * Frame or Dialog that is an owner of the focused Window.
874 * <p>
875 * This method will throw a SecurityException if this KeyboardFocusManager
876 * is not the current KeyboardFocusManager for the calling thread's
877 * context.
878 *
879 * @return the active Window
880 * @see #getActiveWindow
881 * @see #setGlobalActiveWindow
882 * @throws SecurityException if this KeyboardFocusManager is not the
883 * current KeyboardFocusManager for the calling thread's context
884 */
885 protected Window getGlobalActiveWindow() throws SecurityException {
886 synchronized (KeyboardFocusManager.class) {
887 if (this == getCurrentKeyboardFocusManager()) {
888 return activeWindow;
889 } else {
890 if (focusLog.isLoggable(PlatformLogger.FINER)) {
891 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
892 }
893 throw new SecurityException(notPrivileged);
894 }
895 }
896 }
897
898 /**
899 * Sets the active Window. Only a Frame or a Dialog can be the active
900 * Window. The native windowing system may denote the active Window or its
901 * children with special decorations, such as a highlighted title bar. The
902 * active Window is always either the focused Window, or the first Frame or
903 * Dialog that is an owner of the focused Window.
904 * <p>
905 * This method does not actually change the active Window as far as the
906 * native windowing system is concerned. It merely stores the value to be
907 * subsequently returned by <code>getActiveWindow()</code>. Use
908 * <code>Component.requestFocus()</code> or
909 * <code>Component.requestFocusInWindow()</code>to change the active
910 * Window, subject to platform limitations.
911 *
912 * @param activeWindow the active Window
913 * @see #getActiveWindow
914 * @see #getGlobalActiveWindow
915 * @see Component#requestFocus()
916 * @see Component#requestFocusInWindow()
917 * @beaninfo
918 * bound: true
919 */
920 protected void setGlobalActiveWindow(Window activeWindow) {
921 Window oldActiveWindow;
922 synchronized (KeyboardFocusManager.class) {
923 oldActiveWindow = getActiveWindow();
924 if (focusLog.isLoggable(PlatformLogger.FINER)) {
925 focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
926 }
927
928 try {
929 fireVetoableChange("activeWindow", oldActiveWindow,
930 activeWindow);
931 } catch (PropertyVetoException e) {
932 // rejected
933 return;
934 }
935
936 KeyboardFocusManager.activeWindow = activeWindow;
937 }
938
939 firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
940 }
941
942 /**
943 * Returns the default FocusTraversalPolicy. Top-level components
944 * use this value on their creation to initialize their own focus traversal
945 * policy by explicit call to Container.setFocusTraversalPolicy.
946 *
947 * @return the default FocusTraversalPolicy. null will never be returned.
948 * @see #setDefaultFocusTraversalPolicy
949 * @see Container#setFocusTraversalPolicy
950 * @see Container#getFocusTraversalPolicy
951 */
952 public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
953 return defaultPolicy;
954 }
955
956 /**
957 * Sets the default FocusTraversalPolicy. Top-level components
958 * use this value on their creation to initialize their own focus traversal
959 * policy by explicit call to Container.setFocusTraversalPolicy.
960 * Note: this call doesn't affect already created components as they have
961 * their policy initialized. Only new components will use this policy as
962 * their default policy.
963 *
964 * @param defaultPolicy the new, default FocusTraversalPolicy
965 * @see #getDefaultFocusTraversalPolicy
966 * @see Container#setFocusTraversalPolicy
967 * @see Container#getFocusTraversalPolicy
968 * @throws IllegalArgumentException if defaultPolicy is null
969 * @beaninfo
970 * bound: true
971 */
972 public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy
973 defaultPolicy) {
974 if (defaultPolicy == null) {
975 throw new IllegalArgumentException("default focus traversal policy cannot be null");
976 }
977
978 FocusTraversalPolicy oldPolicy;
979
980 synchronized (this) {
981 oldPolicy = this.defaultPolicy;
982 this.defaultPolicy = defaultPolicy;
983 }
984
985 firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
986 defaultPolicy);
987 }
988
989 /**
990 * Sets the default focus traversal keys for a given traversal operation.
991 * This traversal key <code>Set</code> will be in effect on all
992 * <code>Window</code>s that have no such <code>Set</code> of
993 * their own explicitly defined. This <code>Set</code> will also be
994 * inherited, recursively, by any child <code>Component</code> of
995 * those <code>Windows</code> that has
996 * no such <code>Set</code> of its own explicitly defined.
997 * <p>
998 * The default values for the default focus traversal keys are
999 * implementation-dependent. Sun recommends that all implementations for a
1000 * particular native platform use the same default values. The
1001 * recommendations for Windows and Unix are listed below. These
1002 * recommendations are used in the Sun AWT implementations.
1003 *
1004 * <table border=1 summary="Recommended default values for focus traversal keys">
1005 * <tr>
1006 * <th>Identifier</th>
1007 * <th>Meaning</th>
1008 * <th>Default</th>
1009 * </tr>
1010 * <tr>
1011 * <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
1012 * <td>Normal forward keyboard traversal</td>
1013 * <td><code>TAB</code> on <code>KEY_PRESSED</code>,
1014 * <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
1015 * </tr>
1016 * <tr>
1017 * <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
1018 * <td>Normal reverse keyboard traversal</td>
1019 * <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
1020 * <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
1021 * </tr>
1022 * <tr>
1023 * <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
1024 * <td>Go up one focus traversal cycle</td>
1025 * <td>none</td>
1026 * </tr>
1027 * <tr>
1028 * <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
1029 * <td>Go down one focus traversal cycle</td>
1030 * <td>none</td>
1031 * </tr>
1032 * </table>
1033 *
1034 * To disable a traversal key, use an empty <code>Set</code>;
1035 * <code>Collections.EMPTY_SET</code> is recommended.
1036 * <p>
1037 * Using the <code>AWTKeyStroke</code> API, client code can
1038 * specify on which of two
1039 * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
1040 * <code>KEY_RELEASED</code>, the focus traversal operation will
1041 * occur. Regardless of which <code>KeyEvent</code> is specified,
1042 * however, all <code>KeyEvent</code>s related to the focus
1043 * traversal key, including the associated <code>KEY_TYPED</code>
1044 * event, will be consumed, and will not be dispatched
1045 * to any <code>Component</code>. It is a runtime error to
1046 * specify a <code>KEY_TYPED</code> event as
1047 * mapping to a focus traversal operation, or to map the same event to
1048 * multiple default focus traversal operations.
1049 *
1050 * @param id one of
1051 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1052 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1053 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1054 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
1055 * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
1056 * specified operation
1057 * @see #getDefaultFocusTraversalKeys
1058 * @see Component#setFocusTraversalKeys
1059 * @see Component#getFocusTraversalKeys
1060 * @throws IllegalArgumentException if id is not one of
1061 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1062 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1063 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1064 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
1065 * or if keystrokes is <code>null</code>,
1066 * or if keystrokes contains <code>null</code>,
1067 * or if any <code>Object</code> in
1068 * keystrokes is not an <code>AWTKeyStroke</code>,
1069 * or if any keystroke
1070 * represents a <code>KEY_TYPED</code> event,
1071 * or if any keystroke already maps
1072 * to another default focus traversal operation
1073 * @beaninfo
1074 * bound: true
1075 */
1076 public void
1077 setDefaultFocusTraversalKeys(int id,
1078 Set<? extends AWTKeyStroke> keystrokes)
1079 {
1080 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1081 throw new IllegalArgumentException("invalid focus traversal key identifier");
1082 }
1083 if (keystrokes == null) {
1084 throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
1085 }
1086
1087 Set oldKeys;
1088
1089 synchronized (this) {
1090 for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
1091 Object obj = iter.next();
1092
1093 if (obj == null) {
1094 throw new IllegalArgumentException("cannot set null focus traversal key");
1095 }
1096
1097 // Fix for 6195831:
1098 //According to javadoc this method should throw IAE instead of ClassCastException
1099 if (!(obj instanceof AWTKeyStroke)) {
1100 throw new IllegalArgumentException("object is expected to be AWTKeyStroke");
1101 }
1102 AWTKeyStroke keystroke = (AWTKeyStroke)obj;
1103
1104 if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1105 throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
1106 }
1107
1108 // Check to see if key already maps to another traversal
1109 // operation
1110 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
1111 if (i == id) {
1112 continue;
1113 }
1114
1115 if (defaultFocusTraversalKeys[i].contains(keystroke)) {
1116 throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
1117 }
1118 }
1119 }
1120
1121 oldKeys = defaultFocusTraversalKeys[id];
1122 defaultFocusTraversalKeys[id] =
1123 Collections.unmodifiableSet(new HashSet(keystrokes));
1124 }
1125
1126 firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
1127 oldKeys, keystrokes);
1128 }
1129
1130 /**
1131 * Returns a Set of default focus traversal keys for a given traversal
1132 * operation. This traversal key Set will be in effect on all Windows that
1133 * have no such Set of their own explicitly defined. This Set will also be
1134 * inherited, recursively, by any child Component of those Windows that has
1135 * no such Set of its own explicitly defined. (See
1136 * <code>setDefaultFocusTraversalKeys</code> for a full description of each
1137 * operation.)
1138 *
1139 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1140 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1141 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1142 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1143 * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
1144 * for the specified operation; the <code>Set</code>
1145 * will be unmodifiable, and may be empty; <code>null</code>
1146 * will never be returned
1147 * @see #setDefaultFocusTraversalKeys
1148 * @see Component#setFocusTraversalKeys
1149 * @see Component#getFocusTraversalKeys
1150 * @throws IllegalArgumentException if id is not one of
1151 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1152 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1153 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1154 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1155 */
1156 public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
1157 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1158 throw new IllegalArgumentException("invalid focus traversal key identifier");
1159 }
1160
1161 // Okay to return Set directly because it is an unmodifiable view
1162 return defaultFocusTraversalKeys[id];
1163 }
1164
1165 /**
1166 * Returns the current focus cycle root, if the current focus cycle root is
1167 * in the same context as the calling thread. If the focus owner is itself
1168 * a focus cycle root, then it may be ambiguous as to which Components
1169 * represent the next and previous Components to focus during normal focus
1170 * traversal. In that case, the current focus cycle root is used to
1171 * differentiate among the possibilities.
1172 * <p>
1173 * This method is intended to be used only by KeyboardFocusManagers and
1174 * focus implementations. It is not for general client use.
1175 *
1176 * @return the current focus cycle root, or null if the current focus cycle
1177 * root is not a member of the calling thread's context
1178 * @see #getGlobalCurrentFocusCycleRoot
1179 * @see #setGlobalCurrentFocusCycleRoot
1180 */
1181 public Container getCurrentFocusCycleRoot() {
1182 synchronized (KeyboardFocusManager.class) {
1183 if (currentFocusCycleRoot == null) {
1184 return null;
1185 }
1186
1187 return (currentFocusCycleRoot.appContext ==
1188 AppContext.getAppContext())
1189 ? currentFocusCycleRoot
1190 : null;
1191 }
1192 }
1193
1194 /**
1195 * Returns the current focus cycle root, even if the calling thread is in a
1196 * different context than the current focus cycle root. If the focus owner
1197 * is itself a focus cycle root, then it may be ambiguous as to which
1198 * Components represent the next and previous Components to focus during
1199 * normal focus traversal. In that case, the current focus cycle root is
1200 * used to differentiate among the possibilities.
1201 * <p>
1202 * This method will throw a SecurityException if this KeyboardFocusManager
1203 * is not the current KeyboardFocusManager for the calling thread's
1204 * context.
1205 *
1206 * @return the current focus cycle root, or null if the current focus cycle
1207 * root is not a member of the calling thread's context
1208 * @see #getCurrentFocusCycleRoot
1209 * @see #setGlobalCurrentFocusCycleRoot
1210 * @throws SecurityException if this KeyboardFocusManager is not the
1211 * current KeyboardFocusManager for the calling thread's context
1212 */
1213 protected Container getGlobalCurrentFocusCycleRoot()
1214 throws SecurityException
1215 {
1216 synchronized (KeyboardFocusManager.class) {
1217 if (this == getCurrentKeyboardFocusManager()) {
1218 return currentFocusCycleRoot;
1219 } else {
1220 if (focusLog.isLoggable(PlatformLogger.FINER)) {
1221 focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1222 }
1223 throw new SecurityException(notPrivileged);
1224 }
1225 }
1226 }
1227
1228 /**
1229 * Sets the current focus cycle root. If the focus owner is itself a focus
1230 * cycle root, then it may be ambiguous as to which Components represent
1231 * the next and previous Components to focus during normal focus traversal.
1232 * In that case, the current focus cycle root is used to differentiate
1233 * among the possibilities.
1234 * <p>
1235 * This method is intended to be used only by KeyboardFocusManagers and
1236 * focus implementations. It is not for general client use.
1237 *
1238 * @param newFocusCycleRoot the new focus cycle root
1239 * @see #getCurrentFocusCycleRoot
1240 * @see #getGlobalCurrentFocusCycleRoot
1241 * @beaninfo
1242 * bound: true
1243 */
1244 public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
1245 Container oldFocusCycleRoot;
1246
1247 synchronized (KeyboardFocusManager.class) {
1248 oldFocusCycleRoot = getCurrentFocusCycleRoot();
1249 currentFocusCycleRoot = newFocusCycleRoot;
1250 }
1251
1252 firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
1253 newFocusCycleRoot);
1254 }
1255
1256 /**
1257 * Adds a PropertyChangeListener to the listener list. The listener is
1258 * registered for all bound properties of this class, including the
1259 * following:
1260 * <ul>
1261 * <li>whether the KeyboardFocusManager is currently managing focus
1262 * for this application or applet's browser context
1263 * ("managingFocus")</li>
1264 * <li>the focus owner ("focusOwner")</li>
1265 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1266 * <li>the focused Window ("focusedWindow")</li>
1267 * <li>the active Window ("activeWindow")</li>
1268 * <li>the default focus traversal policy
1269 * ("defaultFocusTraversalPolicy")</li>
1270 * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1271 * ("forwardDefaultFocusTraversalKeys")</li>
1272 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1273 * ("backwardDefaultFocusTraversalKeys")</li>
1274 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1275 * ("upCycleDefaultFocusTraversalKeys")</li>
1276 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1277 * ("downCycleDefaultFocusTraversalKeys")</li>
1278 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1279 * </ul>
1280 * If listener is null, no exception is thrown and no action is performed.
1281 *
1282 * @param listener the PropertyChangeListener to be added
1283 * @see #removePropertyChangeListener
1284 * @see #getPropertyChangeListeners
1285 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1286 */
1287 public void addPropertyChangeListener(PropertyChangeListener listener) {
1288 if (listener != null) {
1289 synchronized (this) {
1290 if (changeSupport == null) {
1291 changeSupport = new PropertyChangeSupport(this);
1292 }
1293 changeSupport.addPropertyChangeListener(listener);
1294 }
1295 }
1296 }
1297
1298 /**
1299 * Removes a PropertyChangeListener from the listener list. This method
1300 * should be used to remove the PropertyChangeListeners that were
1301 * registered for all bound properties of this class.
1302 * <p>
1303 * If listener is null, no exception is thrown and no action is performed.
1304 *
1305 * @param listener the PropertyChangeListener to be removed
1306 * @see #addPropertyChangeListener
1307 * @see #getPropertyChangeListeners
1308 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1309 */
1310 public void removePropertyChangeListener(PropertyChangeListener listener) {
1311 if (listener != null) {
1312 synchronized (this) {
1313 if (changeSupport != null) {
1314 changeSupport.removePropertyChangeListener(listener);
1315 }
1316 }
1317 }
1318 }
1319
1320 /**
1321 * Returns an array of all the property change listeners
1322 * registered on this keyboard focus manager.
1323 *
1324 * @return all of this keyboard focus manager's
1325 * <code>PropertyChangeListener</code>s
1326 * or an empty array if no property change
1327 * listeners are currently registered
1328 *
1329 * @see #addPropertyChangeListener
1330 * @see #removePropertyChangeListener
1331 * @see #getPropertyChangeListeners(java.lang.String)
1332 * @since 1.4
1333 */
1334 public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
1335 if (changeSupport == null) {
1336 changeSupport = new PropertyChangeSupport(this);
1337 }
1338 return changeSupport.getPropertyChangeListeners();
1339 }
1340
1341 /**
1342 * Adds a PropertyChangeListener to the listener list for a specific
1343 * property. The specified property may be user-defined, or one of the
1344 * following:
1345 * <ul>
1346 * <li>whether the KeyboardFocusManager is currently managing focus
1347 * for this application or applet's browser context
1348 * ("managingFocus")</li>
1349 * <li>the focus owner ("focusOwner")</li>
1350 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1351 * <li>the focused Window ("focusedWindow")</li>
1352 * <li>the active Window ("activeWindow")</li>
1353 * <li>the default focus traversal policy
1354 * ("defaultFocusTraversalPolicy")</li>
1355 * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1356 * ("forwardDefaultFocusTraversalKeys")</li>
1357 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1358 * ("backwardDefaultFocusTraversalKeys")</li>
1359 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1360 * ("upCycleDefaultFocusTraversalKeys")</li>
1361 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1362 * ("downCycleDefaultFocusTraversalKeys")</li>
1363 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1364 * </ul>
1365 * If listener is null, no exception is thrown and no action is performed.
1366 *
1367 * @param propertyName one of the property names listed above
1368 * @param listener the PropertyChangeListener to be added
1369 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
1370 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1371 * @see #getPropertyChangeListeners(java.lang.String)
1372 */
1373 public void addPropertyChangeListener(String propertyName,
1374 PropertyChangeListener listener) {
1375 if (listener != null) {
1376 synchronized (this) {
1377 if (changeSupport == null) {
1378 changeSupport = new PropertyChangeSupport(this);
1379 }
1380 changeSupport.addPropertyChangeListener(propertyName,
1381 listener);
1382 }
1383 }
1384 }
1385
1386 /**
1387 * Removes a PropertyChangeListener from the listener list for a specific
1388 * property. This method should be used to remove PropertyChangeListeners
1389 * that were registered for a specific bound property.
1390 * <p>
1391 * If listener is null, no exception is thrown and no action is performed.
1392 *
1393 * @param propertyName a valid property name
1394 * @param listener the PropertyChangeListener to be removed
1395 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1396 * @see #getPropertyChangeListeners(java.lang.String)
1397 * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
1398 */
1399 public void removePropertyChangeListener(String propertyName,
1400 PropertyChangeListener listener) {
1401 if (listener != null) {
1402 synchronized (this) {
1403 if (changeSupport != null) {
1404 changeSupport.removePropertyChangeListener(propertyName,
1405 listener);
1406 }
1407 }
1408 }
1409 }
1410
1411 /**
1412 * Returns an array of all the <code>PropertyChangeListener</code>s
1413 * associated with the named property.
1414 *
1415 * @return all of the <code>PropertyChangeListener</code>s associated with
1416 * the named property or an empty array if no such listeners have
1417 * been added.
1418 *
1419 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1420 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1421 * @since 1.4
1422 */
1423 public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
1424 if (changeSupport == null) {
1425 changeSupport = new PropertyChangeSupport(this);
1426 }
1427 return changeSupport.getPropertyChangeListeners(propertyName);
1428 }
1429
1430 /**
1431 * Fires a PropertyChangeEvent in response to a change in a bound property.
1432 * The event will be delivered to all registered PropertyChangeListeners.
1433 * No event will be delivered if oldValue and newValue are the same.
1434 *
1435 * @param propertyName the name of the property that has changed
1436 * @param oldValue the property's previous value
1437 * @param newValue the property's new value
1438 */
1439 protected void firePropertyChange(String propertyName, Object oldValue,
1440 Object newValue)
1441 {
1442 if (oldValue == newValue) {
1443 return;
1444 }
1445 PropertyChangeSupport changeSupport = this.changeSupport;
1446 if (changeSupport != null) {
1447 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
1448 }
1449 }
1450
1451 /**
1452 * Adds a VetoableChangeListener to the listener list. The listener is
1453 * registered for all vetoable properties of this class, including the
1454 * following:
1455 * <ul>
1456 * <li>the focus owner ("focusOwner")</li>
1457 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1458 * <li>the focused Window ("focusedWindow")</li>
1459 * <li>the active Window ("activeWindow")</li>
1460 * </ul>
1461 * If listener is null, no exception is thrown and no action is performed.
1462 *
1463 * @param listener the VetoableChangeListener to be added
1464 * @see #removeVetoableChangeListener
1465 * @see #getVetoableChangeListeners
1466 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1467 */
1468 public void addVetoableChangeListener(VetoableChangeListener listener) {
1469 if (listener != null) {
1470 synchronized (this) {
1471 if (vetoableSupport == null) {
1472 vetoableSupport =
1473 new VetoableChangeSupport(this);
1474 }
1475 vetoableSupport.addVetoableChangeListener(listener);
1476 }
1477 }
1478 }
1479
1480 /**
1481 * Removes a VetoableChangeListener from the listener list. This method
1482 * should be used to remove the VetoableChangeListeners that were
1483 * registered for all vetoable properties of this class.
1484 * <p>
1485 * If listener is null, no exception is thrown and no action is performed.
1486 *
1487 * @param listener the VetoableChangeListener to be removed
1488 * @see #addVetoableChangeListener
1489 * @see #getVetoableChangeListeners
1490 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1491 */
1492 public void removeVetoableChangeListener(VetoableChangeListener listener) {
1493 if (listener != null) {
1494 synchronized (this) {
1495 if (vetoableSupport != null) {
1496 vetoableSupport.removeVetoableChangeListener(listener);
1497 }
1498 }
1499 }
1500 }
1501
1502 /**
1503 * Returns an array of all the vetoable change listeners
1504 * registered on this keyboard focus manager.
1505 *
1506 * @return all of this keyboard focus manager's
1507 * <code>VetoableChangeListener</code>s
1508 * or an empty array if no vetoable change
1509 * listeners are currently registered
1510 *
1511 * @see #addVetoableChangeListener
1512 * @see #removeVetoableChangeListener
1513 * @see #getVetoableChangeListeners(java.lang.String)
1514 * @since 1.4
1515 */
1516 public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
1517 if (vetoableSupport == null) {
1518 vetoableSupport = new VetoableChangeSupport(this);
1519 }
1520 return vetoableSupport.getVetoableChangeListeners();
1521 }
1522
1523 /**
1524 * Adds a VetoableChangeListener to the listener list for a specific
1525 * property. The specified property may be user-defined, or one of the
1526 * following:
1527 * <ul>
1528 * <li>the focus owner ("focusOwner")</li>
1529 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1530 * <li>the focused Window ("focusedWindow")</li>
1531 * <li>the active Window ("activeWindow")</li>
1532 * </ul>
1533 * If listener is null, no exception is thrown and no action is performed.
1534 *
1535 * @param propertyName one of the property names listed above
1536 * @param listener the VetoableChangeListener to be added
1537 * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
1538 * @see #removeVetoableChangeListener
1539 * @see #getVetoableChangeListeners
1540 */
1541 public void addVetoableChangeListener(String propertyName,
1542 VetoableChangeListener listener) {
1543 if (listener != null) {
1544 synchronized (this) {
1545 if (vetoableSupport == null) {
1546 vetoableSupport =
1547 new VetoableChangeSupport(this);
1548 }
1549 vetoableSupport.addVetoableChangeListener(propertyName,
1550 listener);
1551 }
1552 }
1553 }
1554
1555 /**
1556 * Removes a VetoableChangeListener from the listener list for a specific
1557 * property. This method should be used to remove VetoableChangeListeners
1558 * that were registered for a specific bound property.
1559 * <p>
1560 * If listener is null, no exception is thrown and no action is performed.
1561 *
1562 * @param propertyName a valid property name
1563 * @param listener the VetoableChangeListener to be removed
1564 * @see #addVetoableChangeListener
1565 * @see #getVetoableChangeListeners
1566 * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
1567 */
1568 public void removeVetoableChangeListener(String propertyName,
1569 VetoableChangeListener listener) {
1570 if (listener != null) {
1571 synchronized (this) {
1572 if (vetoableSupport != null) {
1573 vetoableSupport.removeVetoableChangeListener(propertyName,
1574 listener);
1575 }
1576 }
1577 }
1578 }
1579
1580 /**
1581 * Returns an array of all the <code>VetoableChangeListener</code>s
1582 * associated with the named property.
1583 *
1584 * @return all of the <code>VetoableChangeListener</code>s associated with
1585 * the named property or an empty array if no such listeners have
1586 * been added.
1587 *
1588 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1589 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1590 * @see #getVetoableChangeListeners
1591 * @since 1.4
1592 */
1593 public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
1594 if (vetoableSupport == null) {
1595 vetoableSupport = new VetoableChangeSupport(this);
1596 }
1597 return vetoableSupport.getVetoableChangeListeners(propertyName);
1598 }
1599
1600 /**
1601 * Fires a PropertyChangeEvent in response to a change in a vetoable
1602 * property. The event will be delivered to all registered
1603 * VetoableChangeListeners. If a VetoableChangeListener throws a
1604 * PropertyVetoException, a new event is fired reverting all
1605 * VetoableChangeListeners to the old value and the exception is then
1606 * rethrown. No event will be delivered if oldValue and newValue are the
1607 * same.
1608 *
1609 * @param propertyName the name of the property that has changed
1610 * @param oldValue the property's previous value
1611 * @param newValue the property's new value
1612 * @throws java.beans.PropertyVetoException if a
1613 * <code>VetoableChangeListener</code> threw
1614 * <code>PropertyVetoException</code>
1615 */
1616 protected void fireVetoableChange(String propertyName, Object oldValue,
1617 Object newValue)
1618 throws PropertyVetoException
1619 {
1620 if (oldValue == newValue) {
1621 return;
1622 }
1623 VetoableChangeSupport vetoableSupport =
1624 this.vetoableSupport;
1625 if (vetoableSupport != null) {
1626 vetoableSupport.fireVetoableChange(propertyName, oldValue,
1627 newValue);
1628 }
1629 }
1630
1631 /**
1632 * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
1633 * chain. This KeyboardFocusManager will request that each
1634 * KeyEventDispatcher dispatch KeyEvents generated by the user before
1635 * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
1636 * notified in the order in which they were added. Notifications will halt
1637 * as soon as one KeyEventDispatcher returns <code>true</code> from its
1638 * <code>dispatchKeyEvent</code> method. There is no limit to the total
1639 * number of KeyEventDispatchers which can be added, nor to the number of
1640 * times which a particular KeyEventDispatcher instance can be added.
1641 * <p>
1642 * If a null dispatcher is specified, no action is taken and no exception
1643 * is thrown.
1644 * <p>
1645 * In a multithreaded application, {@link KeyEventDispatcher} behaves
1646 * the same as other AWT listeners. See
1647 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1648 * >AWT Threading Issues</a> for more details.
1649 *
1650 * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
1651 * @see #removeKeyEventDispatcher
1652 */
1653 public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1654 if (dispatcher != null) {
1655 synchronized (this) {
1656 if (keyEventDispatchers == null) {
1657 keyEventDispatchers = new java.util.LinkedList();
1658 }
1659 keyEventDispatchers.add(dispatcher);
1660 }
1661 }
1662 }
1663
1664 /**
1665 * Removes a KeyEventDispatcher which was previously added to this
1666 * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
1667 * cannot itself be removed, unless it was explicitly re-registered via a
1668 * call to <code>addKeyEventDispatcher</code>.
1669 * <p>
1670 * If a null dispatcher is specified, if the specified dispatcher is not
1671 * in the dispatcher chain, or if this KeyboardFocusManager is specified
1672 * without having been explicitly re-registered, no action is taken and no
1673 * exception is thrown.
1674 * <p>
1675 * In a multithreaded application, {@link KeyEventDispatcher} behaves
1676 * the same as other AWT listeners. See
1677 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1678 * >AWT Threading Issues</a> for more details.
1679 *
1680 * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
1681 * chain
1682 * @see #addKeyEventDispatcher
1683 */
1684 public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1685 if (dispatcher != null) {
1686 synchronized (this) {
1687 if (keyEventDispatchers != null) {
1688 keyEventDispatchers.remove(dispatcher);
1689 }
1690 }
1691 }
1692 }
1693
1694 /**
1695 * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
1696 * The List will not include this KeyboardFocusManager unless it was
1697 * explicitly re-registered via a call to
1698 * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
1699 * registered, implementations are free to return null or a List of length
1700 * 0. Client code should not assume one behavior over another, nor should
1701 * it assume that the behavior, once established, will not change.
1702 *
1703 * @return a possibly null or empty List of KeyEventDispatchers
1704 * @see #addKeyEventDispatcher
1705 * @see #removeKeyEventDispatcher
1706 */
1707 protected synchronized java.util.List<KeyEventDispatcher>
1708 getKeyEventDispatchers()
1709 {
1710 return (keyEventDispatchers != null)
1711 ? (java.util.List)keyEventDispatchers.clone()
1712 : null;
1713 }
1714
1715 /**
1716 * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
1717 * processor chain. After a KeyEvent has been dispatched to and handled by
1718 * its target, KeyboardFocusManager will request that each
1719 * KeyEventPostProcessor perform any necessary post-processing as part
1720 * of the KeyEvent's final resolution. KeyEventPostProcessors
1721 * will be notified in the order in which they were added; the current
1722 * KeyboardFocusManager will be notified last. Notifications will halt
1723 * as soon as one KeyEventPostProcessor returns <code>true</code> from its
1724 * <code>postProcessKeyEvent</code> method. There is no limit to the the
1725 * total number of KeyEventPostProcessors that can be added, nor to the
1726 * number of times that a particular KeyEventPostProcessor instance can be
1727 * added.
1728 * <p>
1729 * If a null post-processor is specified, no action is taken and no
1730 * exception is thrown.
1731 * <p>
1732 * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1733 * the same as other AWT listeners. See
1734 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1735 * >AWT Threading Issues</a> for more details.
1736 *
1737 * @param processor the KeyEventPostProcessor to add to the post-processor
1738 * chain
1739 * @see #removeKeyEventPostProcessor
1740 */
1741 public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
1742 if (processor != null) {
1743 synchronized (this) {
1744 if (keyEventPostProcessors == null) {
1745 keyEventPostProcessors = new java.util.LinkedList();
1746 }
1747 keyEventPostProcessors.add(processor);
1748 }
1749 }
1750 }
1751
1752
1753 /**
1754 * Removes a previously added KeyEventPostProcessor from this
1755 * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
1756 * cannot itself be entirely removed from the chain. Only additional
1757 * references added via <code>addKeyEventPostProcessor</code> can be
1758 * removed.
1759 * <p>
1760 * If a null post-processor is specified, if the specified post-processor
1761 * is not in the post-processor chain, or if this KeyboardFocusManager is
1762 * specified without having been explicitly added, no action is taken and
1763 * no exception is thrown.
1764 * <p>
1765 * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1766 * the same as other AWT listeners. See
1767 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1768 * >AWT Threading Issues</a> for more details.
1769 *
1770 * @param processor the KeyEventPostProcessor to remove from the post-
1771 * processor chain
1772 * @see #addKeyEventPostProcessor
1773 */
1774 public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
1775 if (processor != null) {
1776 synchronized (this) {
1777 if (keyEventPostProcessors != null) {
1778 keyEventPostProcessors.remove(processor);
1779 }
1780 }
1781 }
1782 }
1783
1784
1785 /**
1786 * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
1787 * List. The List will not include this KeyboardFocusManager unless it was
1788 * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
1789 * no KeyEventPostProcessors are registered, implementations are free to
1790 * return null or a List of length 0. Client code should not assume one
1791 * behavior over another, nor should it assume that the behavior, once
1792 * established, will not change.
1793 *
1794 * @return a possibly null or empty List of KeyEventPostProcessors
1795 * @see #addKeyEventPostProcessor
1796 * @see #removeKeyEventPostProcessor
1797 */
1798 protected java.util.List<KeyEventPostProcessor>
1799 getKeyEventPostProcessors()
1800 {
1801 return (keyEventPostProcessors != null)
1802 ? (java.util.List)keyEventPostProcessors.clone()
1803 : null;
1804 }
1805
1806
1807
1808 static void setMostRecentFocusOwner(Component component) {
1809 Component window = component;
1810 while (window != null && !(window instanceof Window)) {
1811 window = window.parent;
1812 }
1813 if (window != null) {
1814 setMostRecentFocusOwner((Window)window, component);
1815 }
1816 }
1817 static synchronized void setMostRecentFocusOwner(Window window,
1818 Component component) {
1819 // ATTN: component has a strong reference to window via chain
1820 // of Component.parent fields. Since WeakHasMap refers to its
1821 // values strongly, we need to break the strong link from the
1822 // value (component) back to its key (window).
1823 WeakReference weakValue = null;
1824 if (component != null) {
1825 weakValue = new WeakReference(component);
1826 }
1827 mostRecentFocusOwners.put(window, weakValue);
1828 }
1829 static void clearMostRecentFocusOwner(Component comp) {
1830 Container window;
1831
1832 if (comp == null) {
1833 return;
1834 }
1835
1836 synchronized (comp.getTreeLock()) {
1837 window = comp.getParent();
1838 while (window != null && !(window instanceof Window)) {
1839 window = window.getParent();
1840 }
1841 }
1842
1843 synchronized (KeyboardFocusManager.class) {
1844 if ((window != null)
1845 && (getMostRecentFocusOwner((Window)window) == comp))
1846 {
1847 setMostRecentFocusOwner((Window)window, null);
1848 }
1849 // Also clear temporary lost component stored in Window
1850 if (window != null) {
1851 Window realWindow = (Window)window;
1852 if (realWindow.getTemporaryLostComponent() == comp) {
1853 realWindow.setTemporaryLostComponent(null);
1854 }
1855 }
1856 }
1857 }
1858
1859 /*
1860 * Please be careful changing this method! It is called from
1861 * javax.swing.JComponent.runInputVerifier() using reflection.
1862 */
1863 static synchronized Component getMostRecentFocusOwner(Window window) {
1864 WeakReference weakValue =
1865 (WeakReference)mostRecentFocusOwners.get(window);
1866 return weakValue == null ? null : (Component)weakValue.get();
1867 }
1868
1869 /**
1870 * This method is called by the AWT event dispatcher requesting that the
1871 * current KeyboardFocusManager dispatch the specified event on its behalf.
1872 * It is expected that all KeyboardFocusManagers will dispatch all
1873 * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
1874 * These events should be dispatched based on the KeyboardFocusManager's
1875 * notion of the focus owner and the focused and active Windows, sometimes
1876 * overriding the source of the specified AWTEvent. Dispatching must be
1877 * done using <code>redispatchEvent</code> to prevent the AWT event
1878 * dispatcher from recursively requesting that the KeyboardFocusManager
1879 * dispatch the event again. If this method returns <code>false</code>,
1880 * then the AWT event dispatcher will attempt to dispatch the event itself.
1881 *
1882 * @param e the AWTEvent to be dispatched
1883 * @return <code>true</code> if this method dispatched the event;
1884 * <code>false</code> otherwise
1885 * @see #redispatchEvent
1886 * @see #dispatchKeyEvent
1887 */
1888 public abstract boolean dispatchEvent(AWTEvent e);
1889
1890 /**
1891 * Redispatches an AWTEvent in such a way that the AWT event dispatcher
1892 * will not recursively request that the KeyboardFocusManager, or any
1893 * installed KeyEventDispatchers, dispatch the event again. Client
1894 * implementations of <code>dispatchEvent</code> and client-defined
1895 * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
1896 * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
1897 * <p>
1898 * This method is intended to be used only by KeyboardFocusManagers and
1899 * KeyEventDispatchers. It is not for general client use.
1900 *
1901 * @param target the Component to which the event should be dispatched
1902 * @param e the event to dispatch
1903 * @see #dispatchEvent
1904 * @see KeyEventDispatcher
1905 */
1906 public final void redispatchEvent(Component target, AWTEvent e) {
1907 e.focusManagerIsDispatching = true;
1908 target.dispatchEvent(e);
1909 e.focusManagerIsDispatching = false;
1910 }
1911
1912 /**
1913 * Typically this method will be called by <code>dispatchEvent</code> if no
1914 * other KeyEventDispatcher in the dispatcher chain dispatched the
1915 * KeyEvent, or if no other KeyEventDispatchers are registered. If an
1916 * implementation of this method returns <code>false</code>,
1917 * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
1918 * may simply return <code>false</code>. If <code>true</code> is returned,
1919 * <code>dispatchEvent</code> should return <code>true</code> as well.
1920 *
1921 * @param e the KeyEvent which the current KeyboardFocusManager has
1922 * requested that this KeyEventDispatcher dispatch
1923 * @return <code>true</code> if the KeyEvent was dispatched;
1924 * <code>false</code> otherwise
1925 * @see #dispatchEvent
1926 */
1927 public abstract boolean dispatchKeyEvent(KeyEvent e);
1928
1929 /**
1930 * This method will be called by <code>dispatchKeyEvent</code>.
1931 * By default, this method will handle any unconsumed KeyEvents that
1932 * map to an AWT <code>MenuShortcut</code> by consuming the event
1933 * and activating the shortcut.
1934 *
1935 * @param e the KeyEvent to post-process
1936 * @return <code>true</code> to indicate that no other
1937 * KeyEventPostProcessor will be notified of the KeyEvent.
1938 * @see #dispatchKeyEvent
1939 * @see MenuShortcut
1940 */
1941 public abstract boolean postProcessKeyEvent(KeyEvent e);
1942
1943 /**
1944 * This method initiates a focus traversal operation if and only if the
1945 * KeyEvent represents a focus traversal key for the specified
1946 * focusedComponent. It is expected that focusedComponent is the current
1947 * focus owner, although this need not be the case. If it is not,
1948 * focus traversal will nevertheless proceed as if focusedComponent
1949 * were the current focus owner.
1950 *
1951 * @param focusedComponent the Component that will be the basis for a focus
1952 * traversal operation if the specified event represents a focus
1953 * traversal key for the Component
1954 * @param e the event that may represent a focus traversal key
1955 */
1956 public abstract void processKeyEvent(Component focusedComponent,
1957 KeyEvent e);
1958
1959 /**
1960 * Called by the AWT to notify the KeyboardFocusManager that it should
1961 * delay dispatching of KeyEvents until the specified Component becomes
1962 * the focus owner. If client code requests a focus change, and the AWT
1963 * determines that this request might be granted by the native windowing
1964 * system, then the AWT will call this method. It is the responsibility of
1965 * the KeyboardFocusManager to delay dispatching of KeyEvents with
1966 * timestamps later than the specified time stamp until the specified
1967 * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
1968 * request by invoking <code>dequeueKeyEvents</code> or
1969 * <code>discardKeyEvents</code>.
1970 *
1971 * @param after timestamp of current event, or the current, system time if
1972 * the current event has no timestamp, or the AWT cannot determine
1973 * which event is currently being handled
1974 * @param untilFocused Component which should receive a FOCUS_GAINED event
1975 * before any pending KeyEvents
1976 * @see #dequeueKeyEvents
1977 * @see #discardKeyEvents
1978 */
1979 protected abstract void enqueueKeyEvents(long after,
1980 Component untilFocused);
1981
1982 /**
1983 * Called by the AWT to notify the KeyboardFocusManager that it should
1984 * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1985 * enqueued because of a call to <code>enqueueKeyEvents</code> with the
1986 * same timestamp and Component should be released for normal dispatching
1987 * to the current focus owner. If the given timestamp is less than zero,
1988 * the outstanding enqueue request for the given Component with the <b>
1989 * oldest</b> timestamp (if any) should be cancelled.
1990 *
1991 * @param after the timestamp specified in the call to
1992 * <code>enqueueKeyEvents</code>, or any value < 0
1993 * @param untilFocused the Component specified in the call to
1994 * <code>enqueueKeyEvents</code>
1995 * @see #enqueueKeyEvents
1996 * @see #discardKeyEvents
1997 */
1998 protected abstract void dequeueKeyEvents(long after,
1999 Component untilFocused);
2000
2001 /**
2002 * Called by the AWT to notify the KeyboardFocusManager that it should
2003 * cancel delayed dispatching of KeyEvents. All KeyEvents which were
2004 * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
2005 * with the same Component should be discarded.
2006 *
2007 * @param comp the Component specified in one or more calls to
2008 * <code>enqueueKeyEvents</code>
2009 * @see #enqueueKeyEvents
2010 * @see #dequeueKeyEvents
2011 */
2012 protected abstract void discardKeyEvents(Component comp);
2013
2014 /**
2015 * Focuses the Component after aComponent, typically based on a
2016 * FocusTraversalPolicy.
2017 *
2018 * @param aComponent the Component that is the basis for the focus
2019 * traversal operation
2020 * @see FocusTraversalPolicy
2021 */
2022 public abstract void focusNextComponent(Component aComponent);
2023
2024 /**
2025 * Focuses the Component before aComponent, typically based on a
2026 * FocusTraversalPolicy.
2027 *
2028 * @param aComponent the Component that is the basis for the focus
2029 * traversal operation
2030 * @see FocusTraversalPolicy
2031 */
2032 public abstract void focusPreviousComponent(Component aComponent);
2033
2034 /**
2035 * Moves the focus up one focus traversal cycle. Typically, the focus owner
2036 * is set to aComponent's focus cycle root, and the current focus cycle
2037 * root is set to the new focus owner's focus cycle root. If, however,
2038 * aComponent's focus cycle root is a Window, then typically the focus
2039 * owner is set to the Window's default Component to focus, and the current
2040 * focus cycle root is unchanged.
2041 *
2042 * @param aComponent the Component that is the basis for the focus
2043 * traversal operation
2044 */
2045 public abstract void upFocusCycle(Component aComponent);
2046
2047 /**
2048 * Moves the focus down one focus traversal cycle. Typically, if
2049 * aContainer is a focus cycle root, then the focus owner is set to
2050 * aContainer's default Component to focus, and the current focus cycle
2051 * root is set to aContainer. If aContainer is not a focus cycle root, then
2052 * no focus traversal operation occurs.
2053 *
2054 * @param aContainer the Container that is the basis for the focus
2055 * traversal operation
2056 */
2057 public abstract void downFocusCycle(Container aContainer);
2058
2059 /**
2060 * Focuses the Component after the current focus owner.
2061 */
2062 public final void focusNextComponent() {
2063 Component focusOwner = getFocusOwner();
2064 if (focusOwner != null) {
2065 focusNextComponent(focusOwner);
2066 }
2067 }
2068
2069 /**
2070 * Focuses the Component before the current focus owner.
2071 */
2072 public final void focusPreviousComponent() {
2073 Component focusOwner = getFocusOwner();
2074 if (focusOwner != null) {
2075 focusPreviousComponent(focusOwner);
2076 }
2077 }
2078
2079 /**
2080 * Moves the focus up one focus traversal cycle from the current focus
2081 * owner. Typically, the new focus owner is set to the current focus
2082 * owner's focus cycle root, and the current focus cycle root is set to the
2083 * new focus owner's focus cycle root. If, however, the current focus
2084 * owner's focus cycle root is a Window, then typically the focus owner is
2085 * set to the focus cycle root's default Component to focus, and the
2086 * current focus cycle root is unchanged.
2087 */
2088 public final void upFocusCycle() {
2089 Component focusOwner = getFocusOwner();
2090 if (focusOwner != null) {
2091 upFocusCycle(focusOwner);
2092 }
2093 }
2094
2095 /**
2096 * Moves the focus down one focus traversal cycle from the current focus
2097 * owner, if and only if the current focus owner is a Container that is a
2098 * focus cycle root. Typically, the focus owner is set to the current focus
2099 * owner's default Component to focus, and the current focus cycle root is
2100 * set to the current focus owner. If the current focus owner is not a
2101 * Container that is a focus cycle root, then no focus traversal operation
2102 * occurs.
2103 */
2104 public final void downFocusCycle() {
2105 Component focusOwner = getFocusOwner();
2106 if (focusOwner instanceof Container) {
2107 downFocusCycle((Container)focusOwner);
2108 }
2109 }
2110
2111 /**
2112 * Dumps the list of focus requests to stderr
2113 */
2114 void dumpRequests() {
2115 System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2116 synchronized (heavyweightRequests) {
2117 for (HeavyweightFocusRequest req : heavyweightRequests) {
2118 System.err.println(">>> Req: " + req);
2119 }
2120 }
2121 System.err.println("");
2122 }
2123
2124 private static final class LightweightFocusRequest {
2125 final Component component;
2126 final boolean temporary;
2127 final CausedFocusEvent.Cause cause;
2128
2129 LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
2130 this.component = component;
2131 this.temporary = temporary;
2132 this.cause = cause;
2133 }
2134 public String toString() {
2135 return "LightweightFocusRequest[component=" + component +
2136 ",temporary=" + temporary + ", cause=" + cause + "]";
2137 }
2138 }
2139
2140 private static final class HeavyweightFocusRequest {
2141 final Component heavyweight;
2142 final LinkedList<LightweightFocusRequest> lightweightRequests;
2143
2144 static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2145 new HeavyweightFocusRequest();
2146
2147 private HeavyweightFocusRequest() {
2148 heavyweight = null;
2149 lightweightRequests = null;
2150 }
2151
2152 HeavyweightFocusRequest(Component heavyweight, Component descendant,
2153 boolean temporary, CausedFocusEvent.Cause cause) {
2154 if (log.isLoggable(PlatformLogger.FINE)) {
2155 if (heavyweight == null) {
2156 log.fine("Assertion (heavyweight != null) failed");
2157 }
2158 }
2159
2160 this.heavyweight = heavyweight;
2161 this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2162 addLightweightRequest(descendant, temporary, cause);
2163 }
2164 boolean addLightweightRequest(Component descendant,
2165 boolean temporary, CausedFocusEvent.Cause cause) {
2166 if (log.isLoggable(PlatformLogger.FINE)) {
2167 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2168 log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2169 }
2170 if (descendant == null) {
2171 log.fine("Assertion (descendant != null) failed");
2172 }
2173 }
2174
2175 Component lastDescendant = ((lightweightRequests.size() > 0)
2176 ? lightweightRequests.getLast().component
2177 : null);
2178
2179 if (descendant != lastDescendant) {
2180 // Not a duplicate request
2181 lightweightRequests.add
2182 (new LightweightFocusRequest(descendant, temporary, cause));
2183 return true;
2184 } else {
2185 return false;
2186 }
2187 }
2188
2189 LightweightFocusRequest getFirstLightweightRequest() {
2190 if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
2191 return null;
2192 }
2193 return lightweightRequests.getFirst();
2194 }
2195 public String toString() {
2196 boolean first = true;
2197 String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
2198 ",lightweightRequests=";
2199 if (lightweightRequests == null) {
2200 str += null;
2201 } else {
2202 str += "[";
2203
2204 for (LightweightFocusRequest lwRequest : lightweightRequests) {
2205 if (first) {
2206 first = false;
2207 } else {
2208 str += ",";
2209 }
2210 str += lwRequest;
2211 }
2212 str += "]";
2213 }
2214 str += "]";
2215 return str;
2216 }
2217 }
2218
2219 /*
2220 * heavyweightRequests is used as a monitor for synchronized changes of
2221 * currentLightweightRequests, clearingCurrentLightweightRequests and
2222 * newFocusOwner.
2223 */
2224 private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
2225 new LinkedList<HeavyweightFocusRequest>();
2226 private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
2227 private static boolean clearingCurrentLightweightRequests;
2228 private static boolean allowSyncFocusRequests = true;
2229 private static Component newFocusOwner = null;
2230 private static volatile boolean disableRestoreFocus;
2231
2232 static final int SNFH_FAILURE = 0;
2233 static final int SNFH_SUCCESS_HANDLED = 1;
2234 static final int SNFH_SUCCESS_PROCEED = 2;
2235
2236 static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
2237 boolean temporary, boolean focusedWindowChangeAllowed,
2238 long time)
2239 {
2240 Window parentWindow = SunToolkit.getContainingWindow(heavyweight);
2241 if (parentWindow == null || !parentWindow.syncLWRequests) {
2242 return false;
2243 }
2244 if (descendant == null) {
2245 // Focus transfers from a lightweight child back to the
2246 // heavyweight Container should be treated like lightweight
2247 // focus transfers.
2248 descendant = heavyweight;
2249 }
2250
2251 KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2252
2253 FocusEvent currentFocusOwnerEvent = null;
2254 FocusEvent newFocusOwnerEvent = null;
2255 Component currentFocusOwner = manager.getGlobalFocusOwner();
2256
2257 synchronized (heavyweightRequests) {
2258 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2259 if (hwFocusRequest == null &&
2260 heavyweight == manager.getNativeFocusOwner() &&
2261 allowSyncFocusRequests)
2262 {
2263
2264 if (descendant == currentFocusOwner) {
2265 // Redundant request.
2266 return true;
2267 }
2268
2269 // 'heavyweight' owns the native focus and there are no pending
2270 // requests. 'heavyweight' must be a Container and
2271 // 'descendant' must not be the focus owner. Otherwise,
2272 // we would never have gotten this far.
2273 manager.enqueueKeyEvents(time, descendant);
2274
2275 hwFocusRequest =
2276 new HeavyweightFocusRequest(heavyweight, descendant,
2277 temporary, CausedFocusEvent.Cause.UNKNOWN);
2278 heavyweightRequests.add(hwFocusRequest);
2279
2280 if (currentFocusOwner != null) {
2281 currentFocusOwnerEvent =
2282 new FocusEvent(currentFocusOwner,
2283 FocusEvent.FOCUS_LOST,
2284 temporary, descendant);
2285 }
2286 newFocusOwnerEvent =
2287 new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2288 temporary, currentFocusOwner);
2289 }
2290 }
2291 boolean result = false;
2292 final boolean clearing = clearingCurrentLightweightRequests;
2293
2294 Throwable caughtEx = null;
2295 try {
2296 clearingCurrentLightweightRequests = false;
2297 synchronized(Component.LOCK) {
2298
2299 if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
2300 ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2301 caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2302 result = true;
2303 }
2304
2305 if (newFocusOwnerEvent != null && descendant != null) {
2306 ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2307 caughtEx = dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent);
2308 result = true;
2309 }
2310 }
2311 } finally {
2312 clearingCurrentLightweightRequests = clearing;
2313 }
2314 if (caughtEx instanceof RuntimeException) {
2315 throw (RuntimeException)caughtEx;
2316 } else if (caughtEx instanceof Error) {
2317 throw (Error)caughtEx;
2318 }
2319 return result;
2320 }
2321
2322 /**
2323 * Indicates whether the native implementation should proceed with a
2324 * pending, native focus request. Before changing the focus at the native
2325 * level, the AWT implementation should always call this function for
2326 * permission. This function will reject the request if a duplicate request
2327 * preceded it, or if the specified heavyweight Component already owns the
2328 * focus and no native focus changes are pending. Otherwise, the request
2329 * will be approved and the focus request list will be updated so that,
2330 * if necessary, the proper descendant will be focused when the
2331 * corresponding FOCUS_GAINED event on the heavyweight is received.
2332 *
2333 * An implementation must ensure that calls to this method and native
2334 * focus changes are atomic. If this is not guaranteed, then the ordering
2335 * of the focus request list may be incorrect, leading to errors in the
2336 * type-ahead mechanism. Typically this is accomplished by only calling
2337 * this function from the native event pumping thread, or by holding a
2338 * global, native lock during invocation.
2339 */
2340 static int shouldNativelyFocusHeavyweight
2341 (Component heavyweight, Component descendant, boolean temporary,
2342 boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
2343 {
2344 if (log.isLoggable(PlatformLogger.FINE)) {
2345 if (heavyweight == null) {
2346 log.fine("Assertion (heavyweight != null) failed");
2347 }
2348 if (time == 0) {
2349 log.fine("Assertion (time != 0) failed");
2350 }
2351 }
2352
2353 if (descendant == null) {
2354 // Focus transfers from a lightweight child back to the
2355 // heavyweight Container should be treated like lightweight
2356 // focus transfers.
2357 descendant = heavyweight;
2358 }
2359
2360 KeyboardFocusManager manager =
2361 getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2362 KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
2363 Component currentFocusOwner = thisManager.getGlobalFocusOwner();
2364 Component nativeFocusOwner = thisManager.getNativeFocusOwner();
2365 Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
2366 if (focusLog.isLoggable(PlatformLogger.FINER)) {
2367 focusLog.finer("SNFH for {0} in {1}",
2368 String.valueOf(descendant), String.valueOf(heavyweight));
2369 }
2370 if (focusLog.isLoggable(PlatformLogger.FINEST)) {
2371 focusLog.finest("0. Current focus owner {0}",
2372 String.valueOf(currentFocusOwner));
2373 focusLog.finest("0. Native focus owner {0}",
2374 String.valueOf(nativeFocusOwner));
2375 focusLog.finest("0. Native focused window {0}",
2376 String.valueOf(nativeFocusedWindow));
2377 }
2378 synchronized (heavyweightRequests) {
2379 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2380 if (focusLog.isLoggable(PlatformLogger.FINEST)) {
2381 focusLog.finest("Request {0}", String.valueOf(hwFocusRequest));
2382 }
2383 if (hwFocusRequest == null &&
2384 heavyweight == nativeFocusOwner)
2385 {
2386 if (descendant == currentFocusOwner) {
2387 // Redundant request.
2388 if (focusLog.isLoggable(PlatformLogger.FINEST))
2389 focusLog.finest("1. SNFH_FAILURE for {0}",
2390 String.valueOf(descendant));
2391 return SNFH_FAILURE;
2392 }
2393
2394 // 'heavyweight' owns the native focus and there are no pending
2395 // requests. 'heavyweight' must be a Container and
2396 // 'descendant' must not be the focus owner. Otherwise,
2397 // we would never have gotten this far.
2398 manager.enqueueKeyEvents(time, descendant);
2399
2400 hwFocusRequest =
2401 new HeavyweightFocusRequest(heavyweight, descendant,
2402 temporary, cause);
2403 heavyweightRequests.add(hwFocusRequest);
2404
2405 if (currentFocusOwner != null) {
2406 FocusEvent currentFocusOwnerEvent =
2407 new CausedFocusEvent(currentFocusOwner,
2408 FocusEvent.FOCUS_LOST,
2409 temporary, descendant, cause);
2410 // Fix 5028014. Rolled out.
2411 // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2412 SunToolkit.postEvent(currentFocusOwner.appContext,
2413 currentFocusOwnerEvent);
2414 }
2415 FocusEvent newFocusOwnerEvent =
2416 new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2417 temporary, currentFocusOwner, cause);
2418 // Fix 5028014. Rolled out.
2419 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2420 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
2421
2422 if (focusLog.isLoggable(PlatformLogger.FINEST))
2423 focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
2424 return SNFH_SUCCESS_HANDLED;
2425 } else if (hwFocusRequest != null &&
2426 hwFocusRequest.heavyweight == heavyweight) {
2427 // 'heavyweight' doesn't have the native focus right now, but
2428 // if all pending requests were completed, it would. Add
2429 // descendant to the heavyweight's list of pending
2430 // lightweight focus transfers.
2431 if (hwFocusRequest.addLightweightRequest(descendant,
2432 temporary, cause)) {
2433 manager.enqueueKeyEvents(time, descendant);
2434 }
2435
2436 if (focusLog.isLoggable(PlatformLogger.FINEST))
2437 focusLog.finest("3. SNFH_HANDLED for lightweight" +
2438 descendant + " in " + heavyweight);
2439 return SNFH_SUCCESS_HANDLED;
2440 } else {
2441 if (!focusedWindowChangeAllowed) {
2442 // For purposes of computing oldFocusedWindow, we should look at
2443 // the second to last HeavyweightFocusRequest on the queue iff the
2444 // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
2445 // there is no second to last HeavyweightFocusRequest, null is an
2446 // acceptable value.
2447 if (hwFocusRequest ==
2448 HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2449 {
2450 int size = heavyweightRequests.size();
2451 hwFocusRequest = (HeavyweightFocusRequest)((size >= 2)
2452 ? heavyweightRequests.get(size - 2)
2453 : null);
2454 }
2455 if (focusedWindowChanged(heavyweight,
2456 (hwFocusRequest != null)
2457 ? hwFocusRequest.heavyweight
2458 : nativeFocusedWindow)) {
2459 if (focusLog.isLoggable(PlatformLogger.FINEST))
2460 focusLog.finest("4. SNFH_FAILURE for " + descendant);
2461 return SNFH_FAILURE;
2462 }
2463 }
2464
2465 manager.enqueueKeyEvents(time, descendant);
2466 heavyweightRequests.add
2467 (new HeavyweightFocusRequest(heavyweight, descendant,
2468 temporary, cause));
2469 if (focusLog.isLoggable(PlatformLogger.FINEST))
2470 focusLog.finest("5. SNFH_PROCEED for " + descendant);
2471 return SNFH_SUCCESS_PROCEED;
2472 }
2473 }
2474 }
2475
2476 /**
2477 * Returns the Window which will be active after processing this request,
2478 * or null if this is a duplicate request. The active Window is useful
2479 * because some native platforms do not support setting the native focus
2480 * owner to null. On these platforms, the obvious choice is to set the
2481 * focus owner to the focus proxy of the active Window.
2482 */
2483 static Window markClearGlobalFocusOwner() {
2484 // need to call this out of synchronized block to avoid possible deadlock
2485 // see 6454631.
2486 final Component nativeFocusedWindow =
2487 getCurrentKeyboardFocusManager().getNativeFocusedWindow();
2488
2489 synchronized (heavyweightRequests) {
2490 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2491 if (hwFocusRequest ==
2492 HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2493 {
2494 // duplicate request
2495 return null;
2496 }
2497
2498 heavyweightRequests.add
2499 (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2500
2501 Component activeWindow = ((hwFocusRequest != null)
2502 ? SunToolkit.getContainingWindow(hwFocusRequest.heavyweight)
2503 : nativeFocusedWindow);
2504 while (activeWindow != null &&
2505 !((activeWindow instanceof Frame) ||
2506 (activeWindow instanceof Dialog)))
2507 {
2508 activeWindow = activeWindow.getParent_NoClientCode();
2509 }
2510
2511 return (Window) activeWindow;
2512 }
2513 }
2514 Component getCurrentWaitingRequest(Component parent) {
2515 synchronized (heavyweightRequests) {
2516 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2517 if (hwFocusRequest != null) {
2518 if (hwFocusRequest.heavyweight == parent) {
2519 LightweightFocusRequest lwFocusRequest =
2520 hwFocusRequest.lightweightRequests.getFirst();
2521 if (lwFocusRequest != null) {
2522 return lwFocusRequest.component;
2523 }
2524 }
2525 }
2526 }
2527 return null;
2528 }
2529
2530 static boolean isAutoFocusTransferEnabled() {
2531 synchronized (heavyweightRequests) {
2532 return (heavyweightRequests.size() == 0)
2533 && !disableRestoreFocus
2534 && (null == currentLightweightRequests);
2535 }
2536 }
2537
2538 static boolean isAutoFocusTransferEnabledFor(Component comp) {
2539 return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal();
2540 }
2541
2542 /*
2543 * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
2544 * @param ex previously caught exception that may be processed right here, or null
2545 * @param comp the component to dispatch the event to
2546 * @param event the event to dispatch to the component
2547 */
2548 static private Throwable dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event) {
2549 Throwable retEx = null;
2550 try {
2551 comp.dispatchEvent(event);
2552 } catch (RuntimeException re) {
2553 retEx = re;
2554 } catch (Error er) {
2555 retEx = er;
2556 }
2557 if (retEx != null) {
2558 if (ex != null) {
2559 handleException(ex);
2560 }
2561 return retEx;
2562 }
2563 return ex;
2564 }
2565
2566 static private void handleException(Throwable ex) {
2567 ex.printStackTrace();
2568 }
2569
2570 static void processCurrentLightweightRequests() {
2571 KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2572 LinkedList<LightweightFocusRequest> localLightweightRequests = null;
2573
2574 Component globalFocusOwner = manager.getGlobalFocusOwner();
2575 if ((globalFocusOwner != null) &&
2576 (globalFocusOwner.appContext != AppContext.getAppContext()))
2577 {
2578 // The current app context differs from the app context of a focus
2579 // owner (and all pending lightweight requests), so we do nothing
2580 // now and wait for a next event.
2581 return;
2582 }
2583
2584 synchronized(heavyweightRequests) {
2585 if (currentLightweightRequests != null) {
2586 clearingCurrentLightweightRequests = true;
2587 disableRestoreFocus = true;
2588 localLightweightRequests = currentLightweightRequests;
2589 allowSyncFocusRequests = (localLightweightRequests.size() < 2);
2590 currentLightweightRequests = null;
2591 } else {
2592 // do nothing
2593 return;
2594 }
2595 }
2596
2597 Throwable caughtEx = null;
2598 try {
2599 if (localLightweightRequests != null) {
2600 Component lastFocusOwner = null;
2601 Component currentFocusOwner = null;
2602
2603 for (Iterator iter = localLightweightRequests.iterator(); iter.hasNext(); ) {
2604
2605 currentFocusOwner = manager.getGlobalFocusOwner();
2606 LightweightFocusRequest lwFocusRequest =
2607 (LightweightFocusRequest)iter.next();
2608
2609 /*
2610 * WARNING: This is based on DKFM's logic solely!
2611 *
2612 * We allow to trigger restoreFocus() in the dispatching process
2613 * only if we have the last request to dispatch. If the last request
2614 * fails, focus will be restored to either the component of the last
2615 * previously succedded request, or to to the focus owner that was
2616 * before this clearing proccess.
2617 */
2618 if (!iter.hasNext()) {
2619 disableRestoreFocus = false;
2620 }
2621
2622 FocusEvent currentFocusOwnerEvent = null;
2623 /*
2624 * We're not dispatching FOCUS_LOST while the current focus owner is null.
2625 * But regardless of whether it's null or not, we're clearing ALL the local
2626 * lw requests.
2627 */
2628 if (currentFocusOwner != null) {
2629 currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
2630 FocusEvent.FOCUS_LOST,
2631 lwFocusRequest.temporary,
2632 lwFocusRequest.component, lwFocusRequest.cause);
2633 }
2634 FocusEvent newFocusOwnerEvent =
2635 new CausedFocusEvent(lwFocusRequest.component,
2636 FocusEvent.FOCUS_GAINED,
2637 lwFocusRequest.temporary,
2638 currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
2639 lwFocusRequest.cause);
2640
2641 if (currentFocusOwner != null) {
2642 ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2643 caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2644 }
2645
2646 ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2647 caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2648
2649 if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2650 lastFocusOwner = lwFocusRequest.component;
2651 }
2652 }
2653 }
2654 } finally {
2655 clearingCurrentLightweightRequests = false;
2656 disableRestoreFocus = false;
2657 localLightweightRequests = null;
2658 allowSyncFocusRequests = true;
2659 }
2660 if (caughtEx instanceof RuntimeException) {
2661 throw (RuntimeException)caughtEx;
2662 } else if (caughtEx instanceof Error) {
2663 throw (Error)caughtEx;
2664 }
2665 }
2666
2667 static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2668 synchronized (heavyweightRequests) {
2669 // Any other case represents a failure condition which we did
2670 // not expect. We need to clearFocusRequestList() and patch up
2671 // the event as best as possible.
2672
2673 if (removeFirstRequest()) {
2674 return (FocusEvent)retargetFocusEvent(fe);
2675 }
2676
2677 Component source = fe.getComponent();
2678 Component opposite = fe.getOppositeComponent();
2679 boolean temporary = false;
2680 if (fe.getID() == FocusEvent.FOCUS_LOST &&
2681 (opposite == null || isTemporary(opposite, source)))
2682 {
2683 temporary = true;
2684 }
2685 return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
2686 CausedFocusEvent.Cause.NATIVE_SYSTEM);
2687 }
2688 }
2689
2690 static FocusEvent retargetFocusGained(FocusEvent fe) {
2691 assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2692
2693 Component currentFocusOwner = getCurrentKeyboardFocusManager().
2694 getGlobalFocusOwner();
2695 Component source = fe.getComponent();
2696 Component opposite = fe.getOppositeComponent();
2697 Component nativeSource = getHeavyweight(source);
2698
2699 synchronized (heavyweightRequests) {
2700 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2701
2702 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2703 {
2704 return retargetUnexpectedFocusEvent(fe);
2705 }
2706
2707 if (source != null && nativeSource == null && hwFocusRequest != null) {
2708 // if source w/o peer and
2709 // if source is equal to first lightweight
2710 // then we should correct source and nativeSource
2711 if (source == hwFocusRequest.getFirstLightweightRequest().component)
2712 {
2713 source = hwFocusRequest.heavyweight;
2714 nativeSource = source; // source is heavuweight itself
2715 }
2716 }
2717 if (hwFocusRequest != null &&
2718 nativeSource == hwFocusRequest.heavyweight)
2719 {
2720 // Focus change as a result of a known call to requestFocus(),
2721 // or known click on a peer focusable heavyweight Component.
2722
2723 heavyweightRequests.removeFirst();
2724
2725 LightweightFocusRequest lwFocusRequest =
2726 hwFocusRequest.lightweightRequests.removeFirst();
2727
2728 Component newSource = lwFocusRequest.component;
2729 if (currentFocusOwner != null) {
2730 /*
2731 * Since we receive FOCUS_GAINED when current focus
2732 * owner is not null, correcponding FOCUS_LOST is supposed
2733 * to be lost. And so, we keep new focus owner
2734 * to determine synthetic FOCUS_LOST event which will be
2735 * generated by KeyboardFocusManager for this FOCUS_GAINED.
2736 *
2737 * This code based on knowledge of
2738 * DefaultKeyboardFocusManager's implementation and might
2739 * be not applicable for another KeyboardFocusManager.
2740 */
2741 newFocusOwner = newSource;
2742 }
2743
2744 boolean temporary = (opposite == null ||
2745 isTemporary(newSource, opposite))
2746 ? false
2747 : lwFocusRequest.temporary;
2748
2749 if (hwFocusRequest.lightweightRequests.size() > 0) {
2750 currentLightweightRequests =
2751 hwFocusRequest.lightweightRequests;
2752 EventQueue.invokeLater(new Runnable() {
2753 public void run() {
2754 processCurrentLightweightRequests();
2755 }
2756 });
2757 }
2758
2759 // 'opposite' will be fixed by
2760 // DefaultKeyboardFocusManager.realOppositeComponent
2761 return new CausedFocusEvent(newSource,
2762 FocusEvent.FOCUS_GAINED, temporary,
2763 opposite, lwFocusRequest.cause);
2764 }
2765
2766 if (currentFocusOwner != null
2767 && currentFocusOwner.getContainingWindow() == source
2768 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2769 {
2770 // Special case for FOCUS_GAINED in top-levels
2771 // If it arrives as the result of activation we should skip it
2772 // This event will not have appropriate request record and
2773 // on arrival there will be already some focus owner set.
2774 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
2775 null, CausedFocusEvent.Cause.ACTIVATION);
2776 }
2777
2778 return retargetUnexpectedFocusEvent(fe);
2779 } // end synchronized(heavyweightRequests)
2780 }
2781
2782 static FocusEvent retargetFocusLost(FocusEvent fe) {
2783 assert (fe.getID() == FocusEvent.FOCUS_LOST);
2784
2785 Component currentFocusOwner = getCurrentKeyboardFocusManager().
2786 getGlobalFocusOwner();
2787 Component opposite = fe.getOppositeComponent();
2788 Component nativeOpposite = getHeavyweight(opposite);
2789
2790 synchronized (heavyweightRequests) {
2791 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2792
2793 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2794 {
2795 if (currentFocusOwner != null) {
2796 // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2797 heavyweightRequests.removeFirst();
2798 return new CausedFocusEvent(currentFocusOwner,
2799 FocusEvent.FOCUS_LOST, false, null,
2800 CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2801 }
2802
2803 // Otherwise, fall through to failure case below
2804
2805 } else if (opposite == null)
2806 {
2807 // Focus leaving application
2808 if (currentFocusOwner != null) {
2809 return new CausedFocusEvent(currentFocusOwner,
2810 FocusEvent.FOCUS_LOST,
2811 true, null, CausedFocusEvent.Cause.ACTIVATION);
2812 } else {
2813 return fe;
2814 }
2815 } else if (hwFocusRequest != null &&
2816 (nativeOpposite == hwFocusRequest.heavyweight ||
2817 nativeOpposite == null &&
2818 opposite == hwFocusRequest.getFirstLightweightRequest().component))
2819 {
2820 if (currentFocusOwner == null) {
2821 return fe;
2822 }
2823 // Focus change as a result of a known call to requestFocus(),
2824 // or click on a peer focusable heavyweight Component.
2825 // If a focus transfer is made across top-levels, then the
2826 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2827 // event is always permanent. Otherwise, the stored temporary
2828 // value is honored.
2829
2830 LightweightFocusRequest lwFocusRequest =
2831 hwFocusRequest.lightweightRequests.getFirst();
2832
2833 boolean temporary = isTemporary(opposite, currentFocusOwner)
2834 ? true
2835 : lwFocusRequest.temporary;
2836
2837 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2838 temporary, lwFocusRequest.component, lwFocusRequest.cause);
2839 } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2840 // If top-level changed there might be no focus request in a list
2841 // But we know the opposite, we now it is temporary - dispatch the event.
2842 if (!fe.isTemporary() && currentFocusOwner != null) {
2843 // Create copy of the event with only difference in temporary parameter.
2844 fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2845 true, opposite, CausedFocusEvent.Cause.ACTIVATION);
2846 }
2847 return fe;
2848 }
2849
2850 return retargetUnexpectedFocusEvent(fe);
2851 } // end synchronized(heavyweightRequests)
2852 }
2853
2854 static AWTEvent retargetFocusEvent(AWTEvent event) {
2855 if (clearingCurrentLightweightRequests) {
2856 return event;
2857 }
2858
2859 KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2860 if (focusLog.isLoggable(PlatformLogger.FINER)) {
2861 if (event instanceof FocusEvent || event instanceof WindowEvent) {
2862 focusLog.finer(">>> {0}", String.valueOf(event));
2863 }
2864 if (focusLog.isLoggable(PlatformLogger.FINER) && event instanceof KeyEvent) {
2865 focusLog.finer(" focus owner is {0}",
2866 String.valueOf(manager.getGlobalFocusOwner()));
2867 focusLog.finer(">>> {0}", String.valueOf(event));
2868 }
2869 }
2870
2871 synchronized(heavyweightRequests) {
2872 /*
2873 * This code handles FOCUS_LOST event which is generated by
2874 * DefaultKeyboardFocusManager for FOCUS_GAINED.
2875 *
2876 * This code based on knowledge of DefaultKeyboardFocusManager's
2877 * implementation and might be not applicable for another
2878 * KeyboardFocusManager.
2879 *
2880 * Fix for 4472032
2881 */
2882 if (newFocusOwner != null &&
2883 event.getID() == FocusEvent.FOCUS_LOST)
2884 {
2885 FocusEvent fe = (FocusEvent)event;
2886
2887 if (manager.getGlobalFocusOwner() == fe.getComponent() &&
2888 fe.getOppositeComponent() == newFocusOwner)
2889 {
2890 newFocusOwner = null;
2891 return event;
2892 }
2893 }
2894 }
2895
2896 processCurrentLightweightRequests();
2897
2898 switch (event.getID()) {
2899 case FocusEvent.FOCUS_GAINED: {
2900 event = retargetFocusGained((FocusEvent)event);
2901 break;
2902 }
2903 case FocusEvent.FOCUS_LOST: {
2904 event = retargetFocusLost((FocusEvent)event);
2905 break;
2906 }
2907 default:
2908 /* do nothing */
2909 }
2910 return event;
2911 }
2912
2913 /**
2914 * Clears markers queue
2915 * This method is not intended to be overridden by KFM's.
2916 * Only DefaultKeyboardFocusManager can implement it.
2917 * @since 1.5
2918 */
2919 void clearMarkers() {
2920 }
2921
2922 static boolean removeFirstRequest() {
2923 KeyboardFocusManager manager =
2924 KeyboardFocusManager.getCurrentKeyboardFocusManager();
2925
2926 synchronized(heavyweightRequests) {
2927 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2928
2929 if (hwFocusRequest != null) {
2930 heavyweightRequests.removeFirst();
2931 if (hwFocusRequest.lightweightRequests != null) {
2932 for (Iterator lwIter = hwFocusRequest.lightweightRequests.
2933 iterator();
2934 lwIter.hasNext(); )
2935 {
2936 manager.dequeueKeyEvents
2937 (-1, ((LightweightFocusRequest)lwIter.next()).
2938 component);
2939 }
2940 }
2941 }
2942 // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2943 // We do it here because this method is called only when problems happen
2944 if (heavyweightRequests.size() == 0) {
2945 manager.clearMarkers();
2946 }
2947 return (heavyweightRequests.size() > 0);
2948 }
2949 }
2950 static void removeLastFocusRequest(Component heavyweight) {
2951 if (log.isLoggable(PlatformLogger.FINE)) {
2952 if (heavyweight == null) {
2953 log.fine("Assertion (heavyweight != null) failed");
2954 }
2955 }
2956
2957 KeyboardFocusManager manager =
2958 KeyboardFocusManager.getCurrentKeyboardFocusManager();
2959 synchronized(heavyweightRequests) {
2960 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2961 if (hwFocusRequest != null &&
2962 hwFocusRequest.heavyweight == heavyweight) {
2963 heavyweightRequests.removeLast();
2964 }
2965 // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2966 // We do it here because this method is called only when problems happen
2967 if (heavyweightRequests.size() == 0) {
2968 manager.clearMarkers();
2969 }
2970 }
2971 }
2972
2973 private static boolean focusedWindowChanged(Component to, Component from) {
2974 Window wto = SunToolkit.getContainingWindow(to);
2975 Window wfrom = SunToolkit.getContainingWindow(from);
2976 if (wto == null && wfrom == null) {
2977 return true;
2978 }
2979 if (wto == null) {
2980 return true;
2981 }
2982 if (wfrom == null) {
2983 return true;
2984 }
2985 return (wto != wfrom);
2986 }
2987
2988 private static boolean isTemporary(Component to, Component from) {
2989 Window wto = SunToolkit.getContainingWindow(to);
2990 Window wfrom = SunToolkit.getContainingWindow(from);
2991 if (wto == null && wfrom == null) {
2992 return false;
2993 }
2994 if (wto == null) {
2995 return true;
2996 }
2997 if (wfrom == null) {
2998 return false;
2999 }
3000 return (wto != wfrom);
3001 }
3002
3003 static Component getHeavyweight(Component comp) {
3004 if (comp == null || comp.getPeer() == null) {
3005 return null;
3006 } else if (comp.getPeer() instanceof LightweightPeer) {
3007 return comp.getNativeContainer();
3008 } else {
3009 return comp;
3010 }
3011 }
3012
3013 static Field proxyActive;
3014 // Accessor to private field isProxyActive of KeyEvent
3015 private static boolean isProxyActiveImpl(KeyEvent e) {
3016 if (proxyActive == null) {
3017 proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction() {
3018 public Object run() {
3019 Field field = null;
3020 try {
3021 field = KeyEvent.class.getDeclaredField("isProxyActive");
3022 if (field != null) {
3023 field.setAccessible(true);
3024 }
3025 } catch (NoSuchFieldException nsf) {
3026 assert(false);
3027 }
3028 return field;
3029 }
3030 });
3031 }
3032
3033 try {
3034 return proxyActive.getBoolean(e);
3035 } catch (IllegalAccessException iae) {
3036 assert(false);
3037 }
3038 return false;
3039 }
3040
3041 // Returns the value of this KeyEvent's field isProxyActive
3042 static boolean isProxyActive(KeyEvent e) {
3043 if (!GraphicsEnvironment.isHeadless()) {
3044 return isProxyActiveImpl(e);
3045 } else {
3046 return false;
3047 }
3048 }
3049
3050 private static HeavyweightFocusRequest getLastHWRequest() {
3051 synchronized(heavyweightRequests) {
3052 return (heavyweightRequests.size() > 0)
3053 ? heavyweightRequests.getLast()
3054 : null;
3055 }
3056 }
3057
3058 private static HeavyweightFocusRequest getFirstHWRequest() {
3059 synchronized(heavyweightRequests) {
3060 return (heavyweightRequests.size() > 0)
3061 ? heavyweightRequests.getFirst()
3062 : null;
3063 }
3064 }
3065 }